mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Merge pull request #3629 from Taha-Mahmoodi/feat/conte-crayon
Effects: Sketch › Conté Crayon draws the dark areas in a black crayon and the light areas in a white one on textured paper
This commit is contained in:
@@ -258,7 +258,7 @@ The scores are self-assessed from our code against public documentation;
|
||||
- reliable exchange of .ai files (layer structure in real files; proprietary editing data isn't written);
|
||||
- an interaction-fidelity pass covering every tool's modifiers and small behaviours;
|
||||
- 3D and Materials beyond the initial live Revolve (Extrude & Bevel, Inflate, Rotate, materials);
|
||||
- most of the raster effects (9 of 57 still missing; Cutout, Film Grain, Neon Glow, Plastic Wrap, Poster Edges, Smudge Stick, Sponge and Watercolor are available under Artistic, Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges and Water Paper under Sketch) and the Effect Gallery;
|
||||
- the Effect Gallery (all 57 Photoshop-style raster filters are available, approximated, under Artistic, Blur, Brush Strokes, Distort, Pixelate, Sharpen, Sketch, Stylize, Texture and Video);
|
||||
- CJK composition for vertical type (vertical type itself has initial support, with a Japanese interface);
|
||||
- scripting, and the rest of Variables (image and graph kinds, dataset import);
|
||||
- generative AI features.
|
||||
|
||||
+6
-3
@@ -29,7 +29,7 @@ blocking it ([Alpha gate](docs/roadmap.md#alpha-gate)).
|
||||
|
||||
| | Value | Kind |
|
||||
|---|---|---|
|
||||
| **Feature breadth** (Illustrator's menu items, tools, effects, formats exist) | **~88%** | measured in part: menu items 348/375 wired (92.8%), tools 89/92, Illustrator effects 46/50, Photoshop effects 54/57, 3D 4/4 (initial types, no materials) |
|
||||
| **Feature breadth** (Illustrator's menu items, tools, effects, formats exist) | **~88%** | measured in part: menu items 348/375 wired (92.8%), tools 89/92, Illustrator effects 46/50, Photoshop effects 57/57, 3D 4/4 (initial types, no materials) |
|
||||
| **Feature depth** (weighted by use, scored by behaviour) | **~75%** | estimated |
|
||||
| **To beta** | **~170–270 h** one agent · ~50–80 h with 4–6 agents | estimated |
|
||||
| **To full parity** | **~360–590 h** one agent · ~95–165 h with 4–6 agents | estimated |
|
||||
@@ -76,7 +76,7 @@ The dimension hours overlap (feature rows hold some UI, format and AI work), so
|
||||
| Strokes, brushes, width profiles | 88% | 8–15 |
|
||||
| Appearance, transparency, graphic styles, masks | 97% | 1–2 |
|
||||
| Live vector effects | 85% | 6–10 |
|
||||
| Raster effects (Effect Gallery) — [effects-parity.md](docs/effects-parity.md) | 82% | 8–14 |
|
||||
| Raster effects (Effect Gallery) — [effects-parity.md](docs/effects-parity.md) | 82% | 4–6 |
|
||||
| 3D and Materials | ~25% | 30–55 |
|
||||
| Type core — [type-parity.md](docs/type-parity.md) | 80% | 14–19 |
|
||||
| Type advanced (CJK, spelling, Touch Type) | 50% | 20–28 |
|
||||
@@ -123,11 +123,13 @@ Ranked; detail in [docs/roadmap.md](docs/roadmap.md) and [docs/gaps.md](docs/gap
|
||||
2. **`.ai` files from real users** (G9): layer structure, guides, speed: 10–20 h.
|
||||
3. **Launch and stability on real machines** (G10): 20–35 h.
|
||||
4. **Core-tool correctness** (G11: Shape Builder regions, Asset Export borders): 8–15 h.
|
||||
5. **Raster effects** (G2) alongside: the 10 remaining filters (7 Artistic, 2 Sketch, 1 more) and the Effect Gallery, 8–14 h.
|
||||
5. **Raster effects** (G2) alongside: the Effect Gallery (every Photoshop-style filter is in), 4–6 h.
|
||||
6. **Then:** type core and advanced type (G4), the Illustrator 2026 additions (G13), 3D (G3).
|
||||
|
||||
## Progress log
|
||||
|
||||
- 2026-10-22: Effect › Sketch › Conté Crayon: a black crayon in the dark areas and a white one in the light areas, on mid-grey paper whose texture (Brick, Burlap, Canvas, Sandstone; Scaling, Relief, Light Direction, Invert) breaks the strokes, with Foreground Level and Background Level; an original approximation, defaults unverified. Every Photoshop-style filter is now in (57/57); the Effect Gallery remains (4–6 h).
|
||||
|
||||
- 2026-10-22: Ruby (ふりがな) for live text: `type.ruby` sets or removes a reading over a byte range of the selected type — above it in horizontal type, right of the column in vertical type (or below/left), start/centre/end aligned, at 1–100% of the base size (default half), overhanging or squeezed to the base width. It is saved in the native file, laid out with its line growing (following lines move on), drawn on the canvas, and written in SVG and PDF as outlines where ruby is present. UI panel and type on a path are next. Headline numbers unchanged.
|
||||
|
||||
- 2026-10-14: Document fonts register every explicitly supplied craft-fonts family after the existing Japanese, Arabic and Thai prefix; optional empty input remains supported. Headline scores and estimates are unchanged.
|
||||
@@ -190,6 +192,7 @@ The full pre-standard record of what landed is kept in [docs/roadmap.md](docs/ro
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Effects: Sketch › Conté Crayon; measured Photoshop-style filters 57/57, the Effect Gallery remains (G2 estimate 4–6 h). |
|
||||
| 2026-10-21 | minor | 3D: original Standard, Diffuse, Top Left and Right lighting presets; command access, effective-setting recognition and preview/history; scores and estimates unchanged |
|
||||
| 2026-10-21 | minor | Print: Japanese paper sizes in the Print dialog's Media list (JIS B4/B5/B6, はがき, 往復はがき, 封筒 長形3号/長形4号/角形2号/角形3号, 四六判); ISO B4/B5 keep their sizes, and a paper is named by id or label, any case and spacing. Headline numbers unchanged. |
|
||||
| 2026-10-17 | minor | Colored Inflate: shared membrane normals and smooth RGB vector ramps replace flat polygon bands; channel groups are batched per solid-fill surface. White-light Inflate retains its original polygons, paint composition and seam joins; the 0.05 seam minimum is restored. Scores and hour estimates unchanged. |
|
||||
|
||||
@@ -598,6 +598,21 @@ pub fn effect_catalog() -> Vec<EffectInfo> {
|
||||
"{detail: 0..10 (4; finer surface texture), smoothness: 0..10 (4; softer relief before the highlights and shadows)} treats the object as polished chrome lit from the top left: bright highlights on high points and dark shadows in low ones, keeping its coverage. Original visual approximation; chosen VectorCraft defaults.",
|
||||
json!({"detail": 4.0, "smoothness": 4.0}),
|
||||
),
|
||||
r(
|
||||
"sketch.conteCrayon",
|
||||
"Conté Crayon…",
|
||||
SKETCH,
|
||||
"{foregroundLevel: 0..20 (12; how far the black crayon reaches from the shadows into the midtones), backgroundLevel: 0..20 (10; how far the white crayon reaches from the highlights into the midtones), texture: \"brick\"|\"burlap\"|\"canvas\"|\"sandstone\" (\"canvas\"; the paper's surface, made in code), scaling: % 50..200 (100), relief: 0..50 (4), lightDirection: \"bottom\"|\"bottomLeft\"|\"left\"|\"topLeft\"|\"top\"|\"topRight\"|\"right\"|\"bottomRight\" (\"top\"), invert: bool (false; turns the surface's heights over)} redraws the object in a dense black crayon in its dark areas and a pure white crayon in its light areas, on mid-grey paper whose texture breaks the strokes and stands in relief, keeping its coverage. Public help names Foreground Level, Background Level and the texture options but not slider ranges or dialog defaults; ranges and defaults here are unverified VectorCraft choices. Original visual approximation, not a proprietary reproduction.",
|
||||
json!({
|
||||
"foregroundLevel": 12.0,
|
||||
"backgroundLevel": 10.0,
|
||||
"texture": "canvas",
|
||||
"scaling": 100.0,
|
||||
"relief": 4.0,
|
||||
"lightDirection": "top",
|
||||
"invert": false
|
||||
}),
|
||||
),
|
||||
r(
|
||||
"sketch.graphicPen",
|
||||
"Graphic Pen…",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//! Poster Edges, Rough Pastels, Smudge Stick, Sponge and Watercolor, Blur › Radial Blur and Smart Blur, Brush Strokes › Accented Edges, Angled Strokes,
|
||||
//! Crosshatch, Dark Strokes, Ink Outlines, Spatter, Sprayed Strokes and Sumi-e, Distort › Diffuse
|
||||
//! Glow, Glass and Ocean Ripple, Pixelate › Color Halftone, Crystallize, Mezzotint and Pointillize,
|
||||
//! Sharpen › Unsharp Mask, Sketch › Bas Relief, Chalk & Charcoal, Charcoal, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster,
|
||||
//! Reticulation, Stamp and Torn Edges, Stylize ›
|
||||
//! Sharpen › Unsharp Mask, Sketch › Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Conté Crayon, Graphic Pen, Halftone Pattern,
|
||||
//! Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges and Water Paper, Stylize ›
|
||||
//! Glowing Edges, Texture
|
||||
//! › Craquelure, Grain, Mosaic Tiles, Patchwork, Stained Glass and Texturizer, and Video ›
|
||||
//! De-Interlace and NTSC Colors): filters over premultiplied RGBA8 pixels.
|
||||
@@ -44,7 +44,7 @@ pub use sketch::{HALFTONE_TYPES, HalftonePattern};
|
||||
pub use texture::{GRAIN_TYPES, Grain, LIGHT_DIRECTIONS, Light, TEXTURES, TEXTURES_LOADED, Texture};
|
||||
|
||||
/// The Photoshop-style effect ids (all raster effects, see [`crate::is_raster`]).
|
||||
pub const PIXEL_EFFECTS: [&str; 55] = [
|
||||
pub const PIXEL_EFFECTS: [&str; 56] = [
|
||||
"artistic.coloredPencil",
|
||||
"artistic.cutout",
|
||||
"artistic.dryBrush",
|
||||
@@ -82,6 +82,7 @@ pub const PIXEL_EFFECTS: [&str; 55] = [
|
||||
"sketch.chalkCharcoal",
|
||||
"sketch.charcoal",
|
||||
"sketch.chrome",
|
||||
"sketch.conteCrayon",
|
||||
"sketch.graphicPen",
|
||||
"sketch.halftonePattern",
|
||||
"sketch.notePaper",
|
||||
@@ -210,6 +211,11 @@ pub enum PixelFx {
|
||||
ChalkCharcoal { chalk: f64, charcoal: f64, pressure: f64 },
|
||||
/// Sketch › Chrome: polished chrome relief with `detail` (0..10) and `smoothness` (0..10).
|
||||
Chrome { detail: f64, smoothness: f64 },
|
||||
/// Sketch › Conté Crayon: dark areas in a black crayon, light areas in a white one, on mid-grey
|
||||
/// paper; `foreground` and `background` (0..20) set how far each crayon reaches into the
|
||||
/// midtones, and the paper is a `texture` surface scaled by `scaling` (0.5..2), in relief as
|
||||
/// strong as `relief` (0..50), lit from `light`, its heights turned over when `invert`.
|
||||
ConteCrayon { foreground: f64, background: f64, texture: Texture, scaling: f64, relief: f64, light: Light, invert: bool },
|
||||
/// Sketch › Graphic Pen: fine linear ink strokes along `dir`, each `length` (1..15) points long
|
||||
/// on white paper; `balance` (0..100) sets how much of the tone range becomes black ink.
|
||||
GraphicPen { length: f64, balance: f64, direction: StrokeDirection },
|
||||
@@ -483,6 +489,15 @@ pub(crate) fn parse(id: &str, p: &Value) -> Option<PixelFx> {
|
||||
pressure: num(p, "strokePressure", 2.0).clamp(0.0, 5.0),
|
||||
},
|
||||
"sketch.chrome" => PixelFx::Chrome { detail: num(p, "detail", 4.0).clamp(0.0, 10.0), smoothness: num(p, "smoothness", 4.0).clamp(0.0, 10.0) },
|
||||
"sketch.conteCrayon" => PixelFx::ConteCrayon {
|
||||
foreground: num(p, "foregroundLevel", 12.0).clamp(0.0, 20.0),
|
||||
background: num(p, "backgroundLevel", 10.0).clamp(0.0, 20.0),
|
||||
texture: Texture::parse(text(p, "texture", "canvas")),
|
||||
scaling: num(p, "scaling", 100.0).clamp(50.0, 200.0) / 100.0,
|
||||
relief: num(p, "relief", 4.0).clamp(0.0, 50.0),
|
||||
light: Light::parse(text(p, "lightDirection", "top")),
|
||||
invert: flag(p, "invert", false),
|
||||
},
|
||||
"sketch.graphicPen" => PixelFx::GraphicPen {
|
||||
length: num(p, "strokeLength", 5.0).clamp(1.0, 15.0),
|
||||
balance: num(p, "lightDarkBalance", 50.0).clamp(0.0, 100.0),
|
||||
@@ -617,6 +632,7 @@ impl PixelFx {
|
||||
PixelFx::UnsharpMask { .. }
|
||||
| PixelFx::ChalkCharcoal { .. }
|
||||
| PixelFx::Chrome { .. }
|
||||
| PixelFx::ConteCrayon { .. }
|
||||
| PixelFx::HalftonePattern { .. }
|
||||
| PixelFx::NotePaper { .. }
|
||||
| PixelFx::Plaster { .. }
|
||||
@@ -692,6 +708,7 @@ impl PixelFx {
|
||||
PixelFx::ColoredPencil { width, .. } => Some(artistic::colored_pencil_reach(width)),
|
||||
PixelFx::ChalkCharcoal { .. } => Some(sketch::CHALK_CHARCOAL_REACH),
|
||||
PixelFx::Chrome { smoothness, .. } => Some(sketch::chrome_reach(smoothness)),
|
||||
PixelFx::ConteCrayon { .. } => Some(sketch::CONTE_REACH),
|
||||
PixelFx::FilmGrain { .. }
|
||||
| PixelFx::Mezzotint { .. }
|
||||
| PixelFx::HalftonePattern { .. }
|
||||
@@ -778,6 +795,9 @@ impl PixelFx {
|
||||
PixelFx::UnsharpMask { amount, radius, threshold } => sharpen::unsharp(px, w, h, amount, to_px(radius), threshold),
|
||||
PixelFx::ChalkCharcoal { chalk, charcoal, pressure } => sketch::chalk_charcoal(px, w, h, space, chalk, charcoal, pressure),
|
||||
PixelFx::Chrome { detail, smoothness } => sketch::chrome(px, w, h, space, detail, smoothness),
|
||||
PixelFx::ConteCrayon { foreground, background, ref texture, scaling, relief, light, invert } => {
|
||||
sketch::conte_crayon(px, w, h, space, foreground, background, texture, scaling, relief, light, invert)
|
||||
}
|
||||
PixelFx::GraphicPen { length, balance, direction } => brushstrokes::graphic_pen(px, w, h, space, length, balance, direction),
|
||||
PixelFx::HalftonePattern { size, contrast, kind } => sketch::halftone_pattern(px, w, h, space, size, contrast, kind),
|
||||
PixelFx::NotePaper { balance, graininess, relief } => sketch::note_paper(px, w, h, space, balance, graininess, relief),
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
//! Effect › Sketch (Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Halftone Pattern, Note Paper, Photocopy, Plaster,
|
||||
//! Reticulation, Stamp, Torn Edges and Water Paper; Graphic Pen lives in
|
||||
//! Effect › Sketch (Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Conté Crayon, Halftone Pattern, Note Paper, Photocopy,
|
||||
//! Plaster, Reticulation, Stamp, Torn Edges and Water Paper; Graphic Pen lives in
|
||||
//! [`super::brushstrokes`]). Original filters built from public behaviour documentation:
|
||||
//! <https://helpx.adobe.com/illustrator/using/summary-effects.html> (Sketch effects redraw in
|
||||
//! black and white; Water Paper flows colours on damp fibrous paper) and the public Photoshop Elements Artistic filters guide. Visual
|
||||
//! approximations, not proprietary reproductions.
|
||||
//! black and white; Water Paper flows colours on damp fibrous paper; Conté Crayon draws dark areas
|
||||
//! in black and light areas in white) and the public Photoshop Elements Sketch filters guide
|
||||
//! (<https://helpx.adobe.com/photoshop-elements/using/sketch-filters.html>: Conté Crayon's
|
||||
//! foreground and background levels and texture options). Visual approximations, not proprietary
|
||||
//! reproductions.
|
||||
|
||||
use std::f64::consts::{FRAC_1_SQRT_2, TAU};
|
||||
|
||||
@@ -12,11 +15,12 @@ use vectorcraft_geom::{Point, Vec2};
|
||||
use super::distort::displace;
|
||||
use super::edges::sobel;
|
||||
use super::pixelate::{Place, cell, rand, value_noise};
|
||||
use super::texture::{Light, Tones, luma, premultiply, smooth_noise, straight};
|
||||
use super::texture::{Light, Texture, Tones, luma, premultiply, smooth_noise, straight, texturizer};
|
||||
use super::{PixelSpace, blur_plane, pick};
|
||||
|
||||
const SALT_CHALK: u64 = 216;
|
||||
const SALT_CHROME: u64 = 0xC40_4D45;
|
||||
const SALT_CONTE: u64 = 0xC047E;
|
||||
const SALT_TORN: u64 = 0x746f726e5f6564;
|
||||
const SALT_WATER: u64 = 208;
|
||||
const EDGE_SOFT: f64 = 0.8;
|
||||
@@ -362,6 +366,78 @@ pub(super) fn reticulation(px: &mut [[u8; 4]], w: usize, h: usize, space: &Pixel
|
||||
});
|
||||
}
|
||||
|
||||
/// How far (document units) Conté Crayon samples the softened tones that choose its crayons.
|
||||
pub(super) const CONTE_REACH: f64 = 3.0 * TONE_SOFT + 1.0;
|
||||
|
||||
/// How much of a crayon is laid down where `amount` (0..1: how dark, for the dark crayon, or how
|
||||
/// light, for the light one) meets its `level` (0..1) and `grain` (0..1, the paper's tooth and the
|
||||
/// stroke): at level 0 only the deepest tones take the crayon, at level 1 it reaches past the
|
||||
/// middle tone; the grain breaks its edge.
|
||||
fn crayon(amount: f64, level: f64, grain: f64) -> f64 {
|
||||
ramp((amount - (0.9 - 0.45 * level) + 0.4 * (grain - 0.5)) / 0.12 + 0.5)
|
||||
}
|
||||
|
||||
/// Conté Crayon: the dark areas drawn in a dense black crayon and the light areas in a pure white
|
||||
/// one, on mid-grey paper whose tooth (`texture` scaled by `scaling` (0.5..2), its heights turned
|
||||
/// over when `invert`) and diagonal strokes break the crayons. `foreground` and `background`
|
||||
/// (0..20) set how far the black and the white crayon reach into the midtones; the paper then
|
||||
/// stands in relief as strong as `relief` (0..50), lit from `light`, as Texturizer draws it.
|
||||
/// Coverage is kept.
|
||||
#[allow(clippy::too_many_arguments)] // the effect's seven options
|
||||
pub(super) fn conte_crayon(
|
||||
px: &mut [[u8; 4]],
|
||||
w: usize,
|
||||
h: usize,
|
||||
space: &PixelSpace,
|
||||
foreground: f64,
|
||||
background: f64,
|
||||
texture: &Texture,
|
||||
scaling: f64,
|
||||
relief: f64,
|
||||
light: Light,
|
||||
invert: bool,
|
||||
) {
|
||||
if !([foreground, background, scaling, relief].iter().all(|v| v.is_finite()) && scaling > 0.0) {
|
||||
return;
|
||||
}
|
||||
let Some(place) = Place::new(space, w, h) else { return };
|
||||
let fg = foreground.clamp(0.0, 20.0) / 20.0;
|
||||
let bg = background.clamp(0.0, 20.0) / 20.0;
|
||||
let tones = Tones::new(px, w, h, TONE_SOFT / place.px);
|
||||
// The tooth: how far the surface stands above its neighbours a quarter point (or half a pixel)
|
||||
// away, so that crayon catches on the peaks and leaves the hollows bare.
|
||||
let step = (0.25f64).max(0.5 * place.px / scaling);
|
||||
let flip = if invert { -1.0 } else { 1.0 };
|
||||
place.each(px, |x, y, p| {
|
||||
if p[3] == 0 {
|
||||
return;
|
||||
}
|
||||
let q = place.at(x, y);
|
||||
let t = Point::new(q.x / scaling, q.y / scaling);
|
||||
let tooth = if t.x.is_finite() && t.y.is_finite() {
|
||||
let at = |dx: f64, dy: f64| texture.height(Point::new(t.x + dx, t.y + dy));
|
||||
let ridge = (at(0.0, 0.0) - 0.25 * (at(-step, 0.0) + at(step, 0.0) + at(0.0, -step) + at(0.0, step))) / step;
|
||||
let tooth = 0.5 + 0.5 * (2.0 * flip * ridge).tanh();
|
||||
if tooth.is_finite() { tooth } else { 0.5 }
|
||||
} else {
|
||||
0.5
|
||||
};
|
||||
// Strokes along the two diagonals, about a point across and several long.
|
||||
let (u, v) = ((q.x + q.y) * FRAC_1_SQRT_2, (q.x - q.y) * FRAC_1_SQRT_2);
|
||||
let dark_stroke = value_noise(SALT_CONTE, u * 1.2, v * 0.15);
|
||||
let light_stroke = value_noise(SALT_CONTE + 1, v * 1.2, u * 0.15);
|
||||
let tone = tones.get(x, y);
|
||||
let black = crayon(1.0 - tone, fg, 0.55 * tooth + 0.45 * dark_stroke);
|
||||
let white = crayon(tone, bg, 0.55 * tooth + 0.45 * light_stroke);
|
||||
let paper = 0.4 + 0.2 * tone;
|
||||
let grey = ((paper + (1.0 - paper) * white) * (1.0 - black)) as f32;
|
||||
*p = premultiply([grey; 3], f32::from(p[3]) / 255.0);
|
||||
});
|
||||
if relief > 0.0 {
|
||||
texturizer(px, w, h, space, texture, scaling, relief, light, invert);
|
||||
}
|
||||
}
|
||||
|
||||
/// Torn Edges: the object in high-contrast black and white with ragged edges. `image_balance`
|
||||
/// (0..50) shifts whether midtones fall to ink or paper; `smoothness` (0..15) softens tones and
|
||||
/// the fraying; `contrast` (0..20) hardens the split. Coverage is kept.
|
||||
|
||||
@@ -1224,6 +1224,8 @@ fn texture_params_take_defaults_and_stay_in_range() {
|
||||
("texture.texturizer", "lightDirection", LIGHT_DIRECTIONS.as_slice()),
|
||||
("artistic.roughPastels", "texture", TEXTURES.as_slice()),
|
||||
("artistic.roughPastels", "lightDirection", LIGHT_DIRECTIONS.as_slice()),
|
||||
("sketch.conteCrayon", "texture", TEXTURES.as_slice()),
|
||||
("sketch.conteCrayon", "lightDirection", LIGHT_DIRECTIONS.as_slice()),
|
||||
] {
|
||||
let doc = crate::effect_info(id).unwrap().params;
|
||||
let parsed: Vec<PixelFx> = table.iter().map(|(_, v)| fx(id, json!({ key: v }))).collect();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Sketch › Bas Relief, Charcoal, Photocopy and Stamp.
|
||||
//! Sketch › Bas Relief, Charcoal, Conté Crayon, Photocopy and Stamp.
|
||||
|
||||
use serde_json::json;
|
||||
use vectorcraft_doc::Effect;
|
||||
@@ -173,9 +173,123 @@ fn bas_relief_lights_the_surfaces_facing_the_light() {
|
||||
|
||||
#[test]
|
||||
fn sketch_filters_reach_beyond_nothing_they_do_not_paint() {
|
||||
for id in ["sketch.basRelief", "sketch.charcoal", "sketch.photocopy", "sketch.stamp"] {
|
||||
for id in ["sketch.basRelief", "sketch.charcoal", "sketch.conteCrayon", "sketch.photocopy", "sketch.stamp"] {
|
||||
let f = fx(id, json!({}));
|
||||
assert_eq!(f.outset(Rect::new(0.0, 0.0, 50.0, 50.0)), 0.0, "{id} keeps the object's coverage");
|
||||
assert!(f.reach().is_some_and(|r| r.is_finite() && r > 0.0), "{id} reach");
|
||||
}
|
||||
}
|
||||
|
||||
/// The mean of channel 0 over columns `x0..x1` of every row.
|
||||
fn mean(d: &[u8], w: usize, h: usize, x0: usize, x1: usize) -> f64 {
|
||||
let sum: u32 = (0..h).flat_map(|y| (x0..x1).map(move |x| (x, y))).map(|(x, y)| u32::from(at(d, w, x, y))).sum();
|
||||
f64::from(sum) / ((x1 - x0) * h) as f64
|
||||
}
|
||||
|
||||
/// How many pixels of channel 0 are lighter than 192.
|
||||
fn white(d: &[u8]) -> usize {
|
||||
d.as_chunks::<4>().0.iter().filter(|p| p[0] > 192).count()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conte_crayon_params_take_defaults_and_stay_in_range() {
|
||||
let defaults = PixelFx::ConteCrayon {
|
||||
foreground: 12.0,
|
||||
background: 10.0,
|
||||
texture: Texture::Canvas,
|
||||
scaling: 1.0,
|
||||
relief: 4.0,
|
||||
light: Light::Top,
|
||||
invert: false,
|
||||
};
|
||||
assert_eq!(fx("sketch.conteCrayon", json!({})), defaults);
|
||||
assert_eq!(
|
||||
fx(
|
||||
"sketch.conteCrayon",
|
||||
json!({"foregroundLevel": -5, "backgroundLevel": 1e308, "texture": "Brick", "scaling": 10, "relief": 99, "lightDirection": "bottomRight", "invert": true})
|
||||
),
|
||||
PixelFx::ConteCrayon {
|
||||
foreground: 0.0,
|
||||
background: 20.0,
|
||||
texture: Texture::Brick,
|
||||
scaling: 0.5,
|
||||
relief: 50.0,
|
||||
light: Light::BottomRight,
|
||||
invert: true
|
||||
}
|
||||
);
|
||||
for junk in [
|
||||
json!({"foregroundLevel": "NaN", "scaling": "1e999"}),
|
||||
json!({"backgroundLevel": null, "texture": 3, "relief": [1], "lightDirection": "up", "invert": "yes"}),
|
||||
] {
|
||||
assert_eq!(fx("sketch.conteCrayon", junk.clone()), defaults, "{junk}");
|
||||
}
|
||||
let doc = crate::effect_info("sketch.conteCrayon").unwrap().params;
|
||||
assert!(doc.contains("unverified") && doc.contains("foregroundLevel") && doc.contains("backgroundLevel"), "{doc}");
|
||||
}
|
||||
|
||||
/// A grey ramp: its shadows in black crayon, its highlights in white crayon, the midtones on grey
|
||||
/// paper between them; grey only, coverage kept, the same on every run.
|
||||
#[test]
|
||||
fn conte_crayon_draws_the_shadows_black_and_the_highlights_white() {
|
||||
let (w, h) = (96, 32);
|
||||
let src = image(w, h, |x, _| grey((x * 255 / (w - 1)) as u8));
|
||||
let out = run("sketch.conteCrayon", json!({"relief": 0}), &src, w, h);
|
||||
for p in out.as_chunks::<4>().0 {
|
||||
assert!(p[0] == p[1] && p[1] == p[2] && p[3] == 255, "{p:?}");
|
||||
}
|
||||
let (shadows, mids, lights) = (mean(&out, w, h, 0, 12), mean(&out, w, h, w / 2 - 6, w / 2 + 6), mean(&out, w, h, w - 12, w));
|
||||
assert!(shadows < 40.0, "shadows {shadows}");
|
||||
assert!(lights > 215.0, "highlights {lights}");
|
||||
assert!(shadows + 30.0 < mids && mids + 30.0 < lights, "{shadows} {mids} {lights}");
|
||||
assert_eq!(out, run("sketch.conteCrayon", json!({"relief": 0}), &src, w, h), "deterministic");
|
||||
// The relief shades the paper but keeps it grey.
|
||||
let lit = run("sketch.conteCrayon", json!({}), &src, w, h);
|
||||
assert_ne!(lit, out);
|
||||
assert!(lit.as_chunks::<4>().0.iter().all(|p| p[0] == p[1] && p[1] == p[2]));
|
||||
}
|
||||
|
||||
/// Foreground Level spreads the black crayon into the midtones, Background Level the white one.
|
||||
#[test]
|
||||
fn conte_crayon_levels_spread_each_crayon_into_the_midtones() {
|
||||
let (w, h) = (64, 64);
|
||||
let mid = image(w, h, |_, _| grey(128));
|
||||
let with = |p: serde_json::Value| run("sketch.conteCrayon", p, &mid, w, h);
|
||||
let (few, many) = (with(json!({"foregroundLevel": 0, "relief": 0})), with(json!({"foregroundLevel": 20, "relief": 0})));
|
||||
assert!(black(&many) > black(&few) + w * h / 4, "{} vs {}", black(&many), black(&few));
|
||||
let (few, many) = (
|
||||
with(json!({"foregroundLevel": 0, "backgroundLevel": 0, "relief": 0})),
|
||||
with(json!({"foregroundLevel": 0, "backgroundLevel": 20, "relief": 0})),
|
||||
);
|
||||
assert!(white(&many) > white(&few) + w * h / 4, "{} vs {}", white(&many), white(&few));
|
||||
}
|
||||
|
||||
/// The paper's texture, scale and inversion break the crayon differently; the relief is lit from
|
||||
/// the chosen side.
|
||||
#[test]
|
||||
fn conte_crayon_texture_options_change_the_paper() {
|
||||
let (w, h) = (64, 64);
|
||||
let mid = image(w, h, |x, y| grey((64 + x + y) as u8));
|
||||
let with = |p: serde_json::Value| run("sketch.conteCrayon", p, &mid, w, h);
|
||||
let canvas = with(json!({"relief": 0}));
|
||||
for other in [
|
||||
json!({"relief": 0, "texture": "brick"}),
|
||||
json!({"relief": 0, "texture": "sandstone"}),
|
||||
json!({"relief": 0, "scaling": 200}),
|
||||
json!({"relief": 0, "invert": true}),
|
||||
] {
|
||||
assert_ne!(with(other.clone()), canvas, "{other}");
|
||||
}
|
||||
let top = with(json!({"texture": "brick", "relief": 20, "lightDirection": "top"}));
|
||||
let bottom = with(json!({"texture": "brick", "relief": 20, "lightDirection": "bottom"}));
|
||||
assert_ne!(top, bottom);
|
||||
assert_ne!(top, with(json!({"texture": "brick", "relief": 0, "lightDirection": "top"})));
|
||||
survives(
|
||||
"sketch.conteCrayon",
|
||||
&[
|
||||
json!({}),
|
||||
json!({"foregroundLevel": "NaN", "backgroundLevel": 1e308, "scaling": -1e308, "relief": 1e308, "texture": "burlap", "invert": true}),
|
||||
json!({"foregroundLevel": -1e308, "backgroundLevel": [1], "texture": {}, "lightDirection": 3, "relief": "NaN"}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,11 +60,12 @@ const PIXELATE: [(&str, &str); 4] =
|
||||
[("pixelate.colorHalftone", "{}"), ("pixelate.crystallize", "{}"), ("pixelate.mezzotint", "{}"), ("pixelate.pointillize", "{}")];
|
||||
|
||||
/// Effect › Sketch, at their defaults.
|
||||
const SKETCH: [(&str, &str); 12] = [
|
||||
const SKETCH: [(&str, &str); 13] = [
|
||||
("sketch.basRelief", "{}"),
|
||||
("sketch.chalkCharcoal", "{}"),
|
||||
("sketch.charcoal", "{}"),
|
||||
("sketch.chrome", "{}"),
|
||||
("sketch.conteCrayon", "{}"),
|
||||
("sketch.graphicPen", "{}"),
|
||||
("sketch.halftonePattern", "{}"),
|
||||
("sketch.notePaper", "{}"),
|
||||
|
||||
@@ -378,6 +378,10 @@ fn structured_junk() {
|
||||
json!({"effect": "artistic.roughPastels", "params": {"strokeLength": 1e308, "strokeDetail": "NaN", "texture": -1e308, "scaling": "bad", "lightDirection": "nope"}}),
|
||||
),
|
||||
("effect.apply", json!({"effect": "sketch.chrome", "params": {"detail": -1e308, "smoothness": "NaN"}})),
|
||||
(
|
||||
"effect.apply",
|
||||
json!({"effect": "sketch.conteCrayon", "params": {"foregroundLevel": "NaN", "backgroundLevel": 1e308, "texture": [1], "scaling": -1e308, "relief": "1e999", "lightDirection": 3, "invert": "yes"}}),
|
||||
),
|
||||
("effect.apply", json!({"effect": "sketch.graphicPen", "params": {"strokeLength": -1e308, "lightDarkBalance": "NaN", "strokeDirection": 3}})),
|
||||
("effect.apply", json!({"effect": "sketch.halftonePattern", "params": {"size": -1e308, "contrast": "NaN", "patternType": 3}})),
|
||||
("effect.apply", json!({"effect": "sketch.basRelief", "params": {"detail": "NaN", "smoothness": 1e308, "lightDirection": 3}})),
|
||||
|
||||
@@ -301,8 +301,8 @@ fn choices(effect: &str, key: &str) -> Option<form::Choices> {
|
||||
("sketch.halftonePattern", "patternType") => Some(&vectorcraft_effects::pixel::HALFTONE_TYPES),
|
||||
("sketch.plaster", "lightDirection") => Some(&vectorcraft_effects::pixel::LIGHT_DIRECTIONS),
|
||||
("texture.grain", "grainType") => Some(&vectorcraft_effects::pixel::GRAIN_TYPES),
|
||||
("texture.texturizer" | "artistic.underpainting", "texture") => Some(&vectorcraft_effects::pixel::TEXTURES),
|
||||
("sketch.basRelief" | "texture.texturizer" | "artistic.underpainting", "lightDirection") => {
|
||||
("texture.texturizer" | "artistic.underpainting" | "sketch.conteCrayon", "texture") => Some(&vectorcraft_effects::pixel::TEXTURES),
|
||||
("sketch.basRelief" | "texture.texturizer" | "artistic.underpainting" | "sketch.conteCrayon", "lightDirection") => {
|
||||
Some(&vectorcraft_effects::pixel::LIGHT_DIRECTIONS)
|
||||
}
|
||||
("video.deinterlace", "eliminate") => Some(&[("Odd Fields", "odd"), ("Even Fields", "even")]),
|
||||
|
||||
@@ -217,6 +217,8 @@ fn raster_filter_dialogs_preview_and_apply() {
|
||||
("pixelate.pointillize", "cellSize", "12"),
|
||||
("sketch.basRelief", "lightDirection", "left"),
|
||||
("sketch.charcoal", "thickness", "5"),
|
||||
("sketch.conteCrayon", "texture", "brick"),
|
||||
("sketch.conteCrayon", "foregroundLevel", "16"),
|
||||
("sketch.halftonePattern", "patternType", "line"),
|
||||
("sketch.photocopy", "darkness", "40"),
|
||||
("sketch.stamp", "lightDarkBalance", "10"),
|
||||
|
||||
@@ -5257,6 +5257,10 @@ theme Appearance Външен вид
|
||||
Halftone Pattern Полутонов шаблон
|
||||
Torn Edges… Разкъсани краища…
|
||||
Torn Edges Разкъсани краища
|
||||
Conté Crayon… Креда Конте…
|
||||
Conté Crayon Креда Конте
|
||||
Foreground Level Ниво на преден план
|
||||
Background Level Ниво на фон
|
||||
Pattern Type Тип шаблон
|
||||
Dot Точка
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5288,6 +5288,10 @@ mark-style Japanese Japonské
|
||||
Halftone Pattern Polotónový vzorek
|
||||
Torn Edges… Roztržené okraje…
|
||||
Torn Edges Roztržené okraje
|
||||
Conté Crayon… Křída Conté…
|
||||
Conté Crayon Křída Conté
|
||||
Foreground Level Úroveň popředí
|
||||
Background Level Úroveň pozadí
|
||||
Pattern Type Typ vzorku
|
||||
Dot Tečka
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5149,6 +5149,10 @@ swatch Bright Violet Kraftig violet
|
||||
Halftone Pattern Rastermønster
|
||||
Torn Edges… Flængede kanter…
|
||||
Torn Edges Flængede kanter
|
||||
Conté Crayon… Conté-kridt…
|
||||
Conté Crayon Conté-kridt
|
||||
Foreground Level Forgrundsniveau
|
||||
Background Level Baggrundsniveau
|
||||
Pattern Type Mønstertype
|
||||
Dot Prik
|
||||
Export Type: Eksporttype:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4867,6 +4867,10 @@ effect Soft Weich
|
||||
Halftone Pattern Rasterungseffekt
|
||||
Torn Edges… Zerrissene Kanten…
|
||||
Torn Edges Zerrissene Kanten
|
||||
Conté Crayon… Conté-Stift…
|
||||
Conté Crayon Conté-Stift
|
||||
Foreground Level Vordergrundstufe
|
||||
Background Level Hintergrundstufe
|
||||
Pattern Type Musterart
|
||||
Dot Punkt
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5240,6 +5240,10 @@ effect Points Σημεία
|
||||
Halftone Pattern Μοτίβο ημιτόνου
|
||||
Torn Edges… Ξεσκισμένες άκρες…
|
||||
Torn Edges Ξεσκισμένες άκρες
|
||||
Conté Crayon… Κιμωλία Conté…
|
||||
Conté Crayon Κιμωλία Conté
|
||||
Foreground Level Επίπεδο προσκηνίου
|
||||
Background Level Επίπεδο φόντου
|
||||
Pattern Type Τύπος μοτίβου
|
||||
Dot Κουκκίδα
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2045 and column 19.
|
@@ -5230,6 +5230,10 @@ mark-style Japanese Japonesas
|
||||
Halftone Pattern Trama de semitonos
|
||||
Torn Edges… Bordes desgarrados…
|
||||
Torn Edges Bordes desgarrados
|
||||
Conté Crayon… Lápiz Conté…
|
||||
Conté Crayon Lápiz Conté
|
||||
Foreground Level Nivel de primer plano
|
||||
Background Level Nivel de fondo
|
||||
Pattern Type Tipo de trama
|
||||
Dot Punto
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5252,6 +5252,10 @@ mark-style Japanese Japanilainen
|
||||
Halftone Pattern Rasterikuvio
|
||||
Torn Edges… Repeytyneet reunat…
|
||||
Torn Edges Repeytyneet reunat
|
||||
Conté Crayon… Conté-liitu…
|
||||
Conté Crayon Conté-liitu
|
||||
Foreground Level Edustan taso
|
||||
Background Level Taustan taso
|
||||
Pattern Type Kuviotyyppi
|
||||
Dot Piste
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5287,6 +5287,10 @@ theme Appearance Apparence
|
||||
Halftone Pattern Trame de demi-teintes
|
||||
Torn Edges… Bords déchirés…
|
||||
Torn Edges Bords déchirés
|
||||
Conté Crayon… Crayon Conté…
|
||||
Conté Crayon Crayon Conté
|
||||
Foreground Level Niveau de premier plan
|
||||
Background Level Niveau d’arrière-plan
|
||||
Pattern Type Type de motif
|
||||
Dot Point
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5274,6 +5274,10 @@ imageTrace Outline Körvonal
|
||||
Halftone Pattern Féltónus minta
|
||||
Torn Edges… Szaggatott szélek…
|
||||
Torn Edges Szaggatott szélek
|
||||
Conté Crayon… Conté-kréta…
|
||||
Conté Crayon Conté-kréta
|
||||
Foreground Level Előtér szintje
|
||||
Background Level Háttér szintje
|
||||
Pattern Type Mintatípus
|
||||
Dot Pont
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5149,6 +5149,10 @@ swatch Bright Violet Violet cerah
|
||||
Halftone Pattern Pola halftone
|
||||
Torn Edges… Tepi robek…
|
||||
Torn Edges Tepi robek
|
||||
Conté Crayon… Krayon Conté…
|
||||
Conté Crayon Krayon Conté
|
||||
Foreground Level Tingkat latar depan
|
||||
Background Level Tingkat latar belakang
|
||||
Pattern Type Jenis pola
|
||||
Dot Titik
|
||||
Export Type: Jenis ekspor:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3816 and column 19.
|
@@ -4902,6 +4902,10 @@ lighting Light Luce
|
||||
Halftone Pattern Pattern mezzetinte
|
||||
Torn Edges… Bordi strappati…
|
||||
Torn Edges Bordi strappati
|
||||
Conté Crayon… Matita Conté…
|
||||
Conté Crayon Matita Conté
|
||||
Foreground Level Livello primo piano
|
||||
Background Level Livello sfondo
|
||||
Pattern Type Tipo di pattern
|
||||
Dot Punto
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4942,6 +4942,10 @@ lighting Light ライト
|
||||
Halftone Pattern ハーフトーンパターン
|
||||
Torn Edges… 破れたエッジ…
|
||||
Torn Edges 破れたエッジ
|
||||
Conté Crayon… コンテ…
|
||||
Conté Crayon コンテ
|
||||
Foreground Level 前景レベル
|
||||
Background Level 背景レベル
|
||||
Pattern Type パターンタイプ
|
||||
Dot ドット
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5005,6 +5005,10 @@ imageTrace Outline კონტური
|
||||
Halftone Pattern ნახევარტონური პატერნი
|
||||
Torn Edges… დაგვერძნილი კიდეები…
|
||||
Torn Edges დაგვერძნილი კიდეები
|
||||
Conté Crayon… კონტე ფანქარი…
|
||||
Conté Crayon კონტე ფანქარი
|
||||
Foreground Level წინა პლანის დონე
|
||||
Background Level ფონის დონე
|
||||
Pattern Type პატერნის ტიპი
|
||||
Dot წერტილი
|
||||
Color Scheme ფერის სქემა
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4865,6 +4865,10 @@ lighting Light 광원
|
||||
Halftone Pattern 하프톤 패턴
|
||||
Torn Edges… 찢어진 가장자리…
|
||||
Torn Edges 찢어진 가장자리
|
||||
Conté Crayon… 콘테 크레용…
|
||||
Conté Crayon 콘테 크레용
|
||||
Foreground Level 전경 레벨
|
||||
Background Level 배경 레벨
|
||||
Pattern Type 패턴 유형
|
||||
Dot 점
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5160,6 +5160,10 @@ swatch Bright Violet Felviolet
|
||||
Halftone Pattern Rasterpatroon
|
||||
Torn Edges… Gescheurde randen…
|
||||
Torn Edges Gescheurde randen
|
||||
Conté Crayon… Conté-krijt…
|
||||
Conté Crayon Conté-krijt
|
||||
Foreground Level Voorgrondniveau
|
||||
Background Level Achtergrondniveau
|
||||
Pattern Type Patroontype
|
||||
Dot Punt
|
||||
Export Type: Exporttype:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5140,6 +5140,10 @@ mark-style Japanese Japońskie
|
||||
Halftone Pattern Wzór rastra
|
||||
Torn Edges… Postrzępione krawędzie…
|
||||
Torn Edges Postrzępione krawędzie
|
||||
Conté Crayon… Kredka Conté…
|
||||
Conté Crayon Kredka Conté
|
||||
Foreground Level Poziom pierwszego planu
|
||||
Background Level Poziom tła
|
||||
Pattern Type Typ wzoru
|
||||
Dot Kropka
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5207,6 +5207,10 @@ mark-style Japanese Japonesas
|
||||
Halftone Pattern Padrão de meio-tom
|
||||
Torn Edges… Bordas rasgadas…
|
||||
Torn Edges Bordas rasgadas
|
||||
Conté Crayon… Lápis Conté…
|
||||
Conté Crayon Lápis Conté
|
||||
Foreground Level Nível do primeiro plano
|
||||
Background Level Nível do plano de fundo
|
||||
Pattern Type Tipo de padrão
|
||||
Dot Ponto
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4898,6 +4898,10 @@ lighting Light Свет
|
||||
Halftone Pattern Полутоновый узор
|
||||
Torn Edges… Рваные края…
|
||||
Torn Edges Рваные края
|
||||
Conté Crayon… Мелок Конте…
|
||||
Conté Crayon Мелок Конте
|
||||
Foreground Level Уровень переднего плана
|
||||
Background Level Уровень фона
|
||||
Pattern Type Тип узора
|
||||
Dot Точка
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5244,6 +5244,10 @@ theme Appearance Utseende
|
||||
Halftone Pattern Rastermönster
|
||||
Torn Edges… Riviga kanter…
|
||||
Torn Edges Riviga kanter
|
||||
Conté Crayon… Contékrita…
|
||||
Conté Crayon Contékrita
|
||||
Foreground Level Förgrundsnivå
|
||||
Background Level Bakgrundsnivå
|
||||
Pattern Type Mönstertyp
|
||||
Dot Punkt
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -5329,6 +5329,10 @@ theme Appearance Görünüm
|
||||
3d Light Işık
|
||||
Torn Edges… Yırtık Kenarlar…
|
||||
Torn Edges Yırtık Kenarlar
|
||||
Conté Crayon… Conté Kalemi…
|
||||
Conté Crayon Conté Kalemi
|
||||
Foreground Level Ön plan düzeyi
|
||||
Background Level Arka plan düzeyi
|
||||
Brush Size Fırça Boyutu
|
||||
Texture Coverage Doku Kapsamı
|
||||
Definition Tanım
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4882,6 +4882,10 @@ lighting Light Світло
|
||||
Halftone Pattern Напівтоновий візерунок
|
||||
Torn Edges… Порвані краї…
|
||||
Torn Edges Порвані краї
|
||||
Conté Crayon… Крейда Конте…
|
||||
Conté Crayon Крейда Конте
|
||||
Foreground Level Рівень переднього плану
|
||||
Background Level Рівень тла
|
||||
Pattern Type Тип візерунка
|
||||
Dot Крапка
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 733 and column 40.
|
@@ -4882,6 +4882,10 @@ theme Appearance Giao diện
|
||||
Halftone Pattern Mẫu bán sắc
|
||||
Torn Edges… Cạnh rách…
|
||||
Torn Edges Cạnh rách
|
||||
Conté Crayon… Bút chì Conté…
|
||||
Conté Crayon Bút chì Conté
|
||||
Foreground Level Mức tiền cảnh
|
||||
Background Level Mức nền
|
||||
Pattern Type Loại mẫu
|
||||
Dot Chấm
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4028 and column 10.
|
@@ -5123,6 +5123,10 @@ lighting Light 光源
|
||||
Halftone Pattern 半调图案
|
||||
Torn Edges… 撕边…
|
||||
Torn Edges 撕边
|
||||
Conté Crayon… 孔特蜡笔…
|
||||
Conté Crayon 孔特蜡笔
|
||||
Foreground Level 前景级别
|
||||
Background Level 背景级别
|
||||
Pattern Type 图案类型
|
||||
Dot 网点
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4934,6 +4934,10 @@ lighting Light 光源
|
||||
Halftone Pattern 半色調圖樣
|
||||
Torn Edges… 撕裂邊緣…
|
||||
Torn Edges 撕裂邊緣
|
||||
Conté Crayon… 孔特蠟筆…
|
||||
Conté Crayon 孔特蠟筆
|
||||
Foreground Level 前景層級
|
||||
Background Level 背景層級
|
||||
Pattern Type 圖樣類型
|
||||
Dot 網點
|
||||
# User Interface › Color Scheme
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -221,6 +221,7 @@ fn effect_menu_lists_the_sketch_filters_between_sharpen_and_stylize() {
|
||||
"Chalk & Charcoal…",
|
||||
"Charcoal…",
|
||||
"Chrome…",
|
||||
"Conté Crayon…",
|
||||
"Graphic Pen…",
|
||||
"Halftone Pattern…",
|
||||
"Note Paper…",
|
||||
@@ -237,19 +238,20 @@ fn effect_menu_lists_the_sketch_filters_between_sharpen_and_stylize() {
|
||||
assert_eq!(sketch[1].params, json!({"effect": "sketch.chalkCharcoal"}));
|
||||
assert_eq!(sketch[2].params, json!({"effect": "sketch.charcoal"}));
|
||||
assert_eq!(sketch[3].params, json!({"effect": "sketch.chrome"}));
|
||||
assert_eq!(sketch[4].params, json!({"effect": "sketch.graphicPen"}));
|
||||
assert_eq!(sketch[5].params, json!({"effect": "sketch.halftonePattern"}));
|
||||
assert_eq!(sketch[6].params, json!({"effect": "sketch.notePaper"}));
|
||||
assert_eq!(sketch[7].params, json!({"effect": "sketch.photocopy"}));
|
||||
assert_eq!(sketch[8].params, json!({"effect": "sketch.plaster"}));
|
||||
assert_eq!(sketch[9].params, json!({"effect": "sketch.reticulation"}));
|
||||
assert_eq!(sketch[10].params, json!({"effect": "sketch.stamp"}));
|
||||
assert_eq!(sketch[11].params, json!({"effect": "sketch.tornEdges"}));
|
||||
assert_eq!(sketch[12].params, json!({"effect": "sketch.waterPaper"}));
|
||||
assert_eq!(sketch[4].params, json!({"effect": "sketch.conteCrayon"}));
|
||||
assert_eq!(sketch[5].params, json!({"effect": "sketch.graphicPen"}));
|
||||
assert_eq!(sketch[6].params, json!({"effect": "sketch.halftonePattern"}));
|
||||
assert_eq!(sketch[7].params, json!({"effect": "sketch.notePaper"}));
|
||||
assert_eq!(sketch[8].params, json!({"effect": "sketch.photocopy"}));
|
||||
assert_eq!(sketch[9].params, json!({"effect": "sketch.plaster"}));
|
||||
assert_eq!(sketch[10].params, json!({"effect": "sketch.reticulation"}));
|
||||
assert_eq!(sketch[11].params, json!({"effect": "sketch.stamp"}));
|
||||
assert_eq!(sketch[12].params, json!({"effect": "sketch.tornEdges"}));
|
||||
assert_eq!(sketch[13].params, json!({"effect": "sketch.waterPaper"}));
|
||||
let at = |label: &str| entries.iter().position(|e| e.path[0] == "Effect" && e.label == label).unwrap();
|
||||
assert!(at("Unsharp Mask…") < at("Bas Relief…") && at("Bas Relief…") < at("Chalk & Charcoal…"));
|
||||
assert!(at("Chalk & Charcoal…") < at("Chrome…"));
|
||||
assert!(at("Chrome…") < at("Graphic Pen…") && at("Graphic Pen…") < at("Halftone Pattern…"));
|
||||
assert!(at("Chrome…") < at("Conté Crayon…") && at("Conté Crayon…") < at("Graphic Pen…") && at("Graphic Pen…") < at("Halftone Pattern…"));
|
||||
assert!(at("Halftone Pattern…") < at("Note Paper…") && at("Note Paper…") < at("Plaster…"));
|
||||
assert!(at("Plaster…") < at("Reticulation…"));
|
||||
assert!(at("Reticulation…") < at("Torn Edges…") && at("Torn Edges…") < at("Water Paper…") && at("Water Paper…") < at("Glowing Edges…"));
|
||||
|
||||
+21
-5
@@ -1,6 +1,6 @@
|
||||
# Effects parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** minor (3D: original Standard, Diffuse, Top Left and Right lighting presets; command access, effective-setting recognition and preview/history; scores and estimates unchanged; G2: Effect › Sketch › Note Paper; Halftone Pattern and Note Paper defaults documented as unverified VectorCraft choices; G2: Effect › Artistic › Smudge Stick, Sponge and Watercolor; Sketch › Bas Relief, Charcoal, Photocopy and Stamp, #2533; Photoshop filters 46/57, 11 remaining (8–14 h); G2: Sketch › Chrome; Sketch › Chalk & Charcoal, Graphic Pen and Reticulation and Artistic › Plastic Wrap, #2972, #2967, #2976, #3034: 37/57 Photoshop effects; 3D lighting: one to ten colored lights, smooth colored Inflate, legacy white-light appearance preserved; surface batching and restored seam minimum; scores and estimates unchanged; Zig Zag's Smooth points make a continuous wave, #2343; G2: Effect › Sketch › Halftone Pattern; Photoshop filters 46/57, 11 remaining (8–14 h); Round Corners also rounds corners where a curve meets a line or another curve, with Live Corners' cut; straight corners unchanged; score unchanged; Revolve: automatic smooth shading and default-on Cap with continuous rims; wide shadows and glows at high zoom, #1706; stacked Transform effects, #1705; 3D on nonzero compound paths, #1724; pattern tiles redraw, #1723; scores unchanged; Roughen's Smooth turn-backs, #1643; Scribble per region, #1648; score unchanged; Warp Arc bends in the object's proportions, #1578; Zig Zag ridges evenly spaced, #1558; effect parameters checked, #1592; score unchanged; raster effects after a pattern, radial or freeform gradient fill export at their place and size, #1536; score unchanged; 3D and Materials on outlined type and other shapes of many small curves, #1481; Twist 0° to 360°, #1524; twisted walls keep their faces, #1525; score unchanged; 3D and Materials: Inflate takes Twist, Taper and Cap; score unchanged; 3D and Materials: Perspective as the documented 0°–160° angle; 3D and Materials: the documented light settings) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-22 · **Change:** minor (G2: Effect › Sketch › Conté Crayon (Foreground Level, Background Level, Texture, Scaling, Relief, Light Direction, Invert; a black crayon in the dark areas and a white one in the light areas on textured mid-grey paper; ranges and defaults unverified VectorCraft choices); measured Photoshop-style filters 57/57, the Effect Gallery remains (4–6 h); 3D: original Standard, Diffuse, Top Left and Right lighting presets; command access, effective-setting recognition and preview/history; scores and estimates unchanged; G2: Effect › Sketch › Note Paper; Halftone Pattern and Note Paper defaults documented as unverified VectorCraft choices; G2: Effect › Artistic › Smudge Stick, Sponge and Watercolor; Sketch › Bas Relief, Charcoal, Photocopy and Stamp, #2533; Photoshop filters 46/57, 11 remaining (8–14 h); G2: Sketch › Chrome; Sketch › Chalk & Charcoal, Graphic Pen and Reticulation and Artistic › Plastic Wrap, #2972, #2967, #2976, #3034: 37/57 Photoshop effects; 3D lighting: one to ten colored lights, smooth colored Inflate, legacy white-light appearance preserved; surface batching and restored seam minimum; scores and estimates unchanged; Zig Zag's Smooth points make a continuous wave, #2343; G2: Effect › Sketch › Halftone Pattern; Photoshop filters 46/57, 11 remaining (8–14 h); Round Corners also rounds corners where a curve meets a line or another curve, with Live Corners' cut; straight corners unchanged; score unchanged; Revolve: automatic smooth shading and default-on Cap with continuous rims; wide shadows and glows at high zoom, #1706; stacked Transform effects, #1705; 3D on nonzero compound paths, #1724; pattern tiles redraw, #1723; scores unchanged; Roughen's Smooth turn-backs, #1643; Scribble per region, #1648; score unchanged; Warp Arc bends in the object's proportions, #1578; Zig Zag ridges evenly spaced, #1558; effect parameters checked, #1592; score unchanged; raster effects after a pattern, radial or freeform gradient fill export at their place and size, #1536; score unchanged; 3D and Materials on outlined type and other shapes of many small curves, #1481; Twist 0° to 360°, #1524; twisted walls keep their faces, #1525; score unchanged; 3D and Materials: Inflate takes Twist, Taper and Cap; score unchanged; 3D and Materials: Perspective as the documented 0°–160° angle; 3D and Materials: the documented light settings) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
|
||||
Every entry of Illustrator's Effect menu, by its public feature name, against VectorCraft's effects catalogue
|
||||
(`effect_catalog()` in `crates/effects/src/lib.rs`) and the Effect menu built from it
|
||||
@@ -12,7 +12,7 @@ Part of [target-app-parity.md](target-app-parity.md); open work is in [gaps.md](
|
||||
| Group | Illustrator | VectorCraft | % | Remaining (h) |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Illustrator effects (vector and stylize) | 50 | 46 | 92% | 6–10 |
|
||||
| Photoshop effects (raster, Effect Gallery) | 57 | 54 | 95% | 2–4 |
|
||||
| Photoshop effects (raster, Effect Gallery) | 57 | 57 | 100% | 4–6 (the Effect Gallery) |
|
||||
| 3D and Materials | 4 (+3 Classic) | 4 (initial: Extrude & Bevel, Revolve, Inflate, Rotate) | ~25% | 25–45 |
|
||||
| Beyond Illustrator: Effect › Color Adjustments (6), effect plug-ins (WebAssembly) | — | 6 + plug-ins | — | — |
|
||||
|
||||
@@ -44,7 +44,7 @@ its resolution, PDF export warns once per object with the requested and the lowe
|
||||
| Distort | Diffuse Glow, Glass, Ocean Ripple | 3/3 | — |
|
||||
| Pixelate | Color Halftone, Crystallize, Mezzotint, Pointillize | 4/4 | — |
|
||||
| Sharpen | Unsharp Mask | 1/1 | — |
|
||||
| Sketch | Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Conté Crayon, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges, Water Paper | 13/14 (approximate Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges, Water Paper; Chalk & Charcoal, Graphic Pen, Note Paper and Water Paper defaults unverified) | Conté Crayon |
|
||||
| Sketch | Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Conté Crayon, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges, Water Paper | 14/14 (approximate Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Conté Crayon, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges, Water Paper; Chalk & Charcoal, Conté Crayon, Graphic Pen, Note Paper and Water Paper defaults unverified) | — |
|
||||
| Stylize | Glowing Edges | 1/1 | — |
|
||||
| Texture | Craquelure, Grain, Mosaic Tiles, Patchwork, Stained Glass, Texturizer | 6/6 | — |
|
||||
| Video | De-Interlace, NTSC Colors | 2/2 | — |
|
||||
@@ -52,8 +52,8 @@ its resolution, PDF export warns once per object with the requested and the lowe
|
||||
|
||||
The pixel-filter pipeline (`vectorcraft_effects::pixel`) is in place: each new filter is one function, a
|
||||
catalogue row, a menu entry and translations. Measured throughput: 0.7–1.2 agent hours per filter
|
||||
(see [calibration](target-app-parity.md#calibration)), so the 3 missing filters are ~2–4 h and the Effect
|
||||
Gallery dialog another 4–6 h. These parallelize well across agents.
|
||||
(see [calibration](target-app-parity.md#calibration)). Every Photoshop-style filter is in the catalogue; the Effect
|
||||
Gallery dialog is the 4–6 h that remain.
|
||||
|
||||
Film Grain (`artistic.filmGrain`, Effect › Artistic) adds stable monochrome noise to shadows and
|
||||
midtones, with Grain, Highlight Area and Intensity sliders, live preview and appearance editing.
|
||||
@@ -159,6 +159,21 @@ for VectorCraft and are not verified against proprietary defaults. Evidence: `cr
|
||||
`halftone_pattern_settings_survive_a_save_and_open` in `crates/engine/src/tests_rasterfilters.rs`, and
|
||||
`tests_labels::effect_menu_lists_the_sketch_filters_between_sharpen_and_stylize`.
|
||||
|
||||
Effect › Sketch › Conté Crayon (`sketch.conteCrayon`; `pixel/sketch.rs`) redraws the object in a dense
|
||||
black crayon where it is dark and a pure white crayon where it is light, on mid-grey paper, as
|
||||
[Illustrator's public effects summary](https://helpx.adobe.com/illustrator/using/summary-effects.html) describes
|
||||
(black for dark areas, white for light areas). Its controls follow the public
|
||||
[Photoshop filter reference](https://helpx.adobe.com/photoshop/using/filter-effects-reference.html) and the
|
||||
[Photoshop Elements Sketch filters guide](https://helpx.adobe.com/photoshop-elements/using/sketch-filters.html)
|
||||
(foreground and background levels, texture options): Foreground Level and Background Level (0–20) set how far
|
||||
each crayon reaches into the midtones; Texture (Brick, Burlap, Canvas, Sandstone, the surfaces Texturizer
|
||||
draws), Scaling, Relief, Light Direction and Invert make the paper's tooth, which breaks the diagonal crayon
|
||||
strokes, and its relief. The public pages publish no slider ranges or defaults, so those are unverified
|
||||
VectorCraft choices; an original approximation, never compared with another application's output. Tests:
|
||||
`pixel::tests_sketch::conte_crayon_*`, `tests_rasterfilters`, `command_sweep`,
|
||||
`dialogs::tests::raster_filter_dialogs_preview_and_apply` and
|
||||
`tests_labels::effect_menu_lists_the_sketch_filters_between_sharpen_and_stylize`.
|
||||
|
||||
## 3D and Materials
|
||||
|
||||
| Item | Ours |
|
||||
@@ -178,6 +193,7 @@ angular cut caps, exact visibility, 3D Classic, Turntable, 3D export) is 25–45
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | G2: Effect › Sketch › Conté Crayon (Foreground Level, Background Level, Texture, Scaling, Relief, Light Direction, Invert; a black crayon in the dark areas and a white one in the light areas on textured mid-grey paper; ranges and defaults unverified VectorCraft choices); measured Photoshop-style filters 57/57, the Effect Gallery remains (4–6 h); Sketch 14/14. |
|
||||
| 2026-10-21 | minor | 3D: original Standard, Diffuse, Top Left and Right lighting presets; command access, effective-setting recognition and preview/history; scores and estimates unchanged |
|
||||
| 2026-10-20 | minor | G2: Effect › Sketch › Water Paper (Fiber Length, Brightness, Contrast; colours flow on damp fibrous paper, defaults unverified, #2955); measured Photoshop filters 47/57, Sketch 12/14. |
|
||||
| 2026-10-20 | minor | G2: Effect › Sketch › Note Paper (Image Balance, Graininess, Relief; embossed tones on fibrous paper); Halftone Pattern and Note Paper parameter ranges follow public control names, numeric defaults are unverified VectorCraft choices (public help gives no numbers); measured Photoshop filters 46/57, Sketch 11/14. |
|
||||
|
||||
+9
-9
File diff suppressed because one or more lines are too long
+4
-3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user