mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 17:56:50 -06:00
G2: Effect › Artistic › Colored Pencil raster filter
Squashed from #3028 onto main.
This commit is contained in:
@@ -350,6 +350,13 @@ pub fn effect_catalog() -> Vec<EffectInfo> {
|
||||
),
|
||||
r("stylize.feather", "Feather…", STYLIZE, "{radius: pt (5)}", json!({"radius": 5.0})),
|
||||
r("blur.gaussian", "Gaussian Blur…", BLUR, "{radius: pt (5)}", json!({"radius": 5.0})),
|
||||
r(
|
||||
"artistic.coloredPencil",
|
||||
"Colored Pencil…",
|
||||
ARTISTIC,
|
||||
"{pencilWidth: 1..24 (5; stroke spacing in document units), strokePressure: 0..15 (5; how heavily the strokes darken), paperBrightness: 0..50 (25; lifts lighter areas toward the paper)} redraws the object in coloured pencil strokes along its edges, keeping its hues and coverage. Original visual approximation; chosen VectorCraft defaults.",
|
||||
json!({"pencilWidth": 5.0, "strokePressure": 5.0, "paperBrightness": 25.0}),
|
||||
),
|
||||
r(
|
||||
"artistic.cutout",
|
||||
"Cutout…",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Effect › Artistic (Cutout, Dry Brush, Film Grain, Neon Glow, Paint Daubs, Palette Knife, Plastic Wrap, Poster
|
||||
//! Effect › Artistic (Colored Pencil, Cutout, Dry Brush, Film Grain, Neon Glow, Paint Daubs, Palette Knife, Plastic Wrap, Poster
|
||||
//! Edges, Rough Pastels, Smudge Stick, Sponge, Underpainting and Watercolor). Original filters built from
|
||||
//! public behaviour documentation:
|
||||
//! <https://helpx.adobe.com/illustrator/using/summary-effects.html> and
|
||||
@@ -71,6 +71,7 @@ impl PaintDaubBrush {
|
||||
pub(super) fn paint_daub_radius(size: f64) -> f64 {
|
||||
size.clamp(1.0, 50.0) * 0.48
|
||||
}
|
||||
const SALT_PENCIL: u64 = 304;
|
||||
|
||||
/// Keep the last cell's four corner values: magnified adjacent pixels often share a cell.
|
||||
/// The cache changes only cost, never the field, and needs constant storage per raster.
|
||||
@@ -219,6 +220,55 @@ fn planes(px: &[[u8; 4]]) -> ([Vec<f32>; 3], Vec<f32>) {
|
||||
(std::array::from_fn(|k| colours.iter().map(|c| c[k]).collect()), px.iter().map(|p| f32::from(p[3]) / 255.0).collect())
|
||||
}
|
||||
|
||||
/// How far (document units) Colored Pencil reaches at pencil width `width`: soften at
|
||||
/// `0.12 * width` and the Sobel neighbourhood around it.
|
||||
pub(super) fn colored_pencil_reach(width: f64) -> f64 {
|
||||
3.0 * 0.12 * width.clamp(1.0, 24.0) + 1.0
|
||||
}
|
||||
|
||||
/// Colored Pencil: the object redrawn with coloured pencil strokes along local edges, keeping its
|
||||
/// hues. `width` (1..24) sets the stroke spacing in document units; `pressure` (0..15) darkens
|
||||
/// along the strokes; `paper` (0..50) lifts lighter areas toward the paper. Coverage is kept.
|
||||
pub(super) fn colored_pencil(px: &mut [[u8; 4]], w: usize, h: usize, space: &PixelSpace, width: f64, pressure: f64, paper: f64) {
|
||||
if !([width, pressure, paper].iter().all(|v| v.is_finite()) && space.px.is_finite() && space.px > 0.0) {
|
||||
return;
|
||||
}
|
||||
let width = width.clamp(1.0, 24.0);
|
||||
let pressure = (pressure / 15.0).clamp(0.0, 1.0) as f32;
|
||||
let paper_lift = (paper / 50.0).clamp(0.0, 1.0) as f32;
|
||||
if pressure == 0.0 && paper_lift == 0.0 {
|
||||
return;
|
||||
}
|
||||
let Some(place) = Place::new(space, w, h) else { return };
|
||||
let (mut colour, alpha) = planes(px);
|
||||
soften(&mut colour, &alpha, w, h, (0.12 * width) / space.px);
|
||||
let tones: Vec<f32> = (0..px.len()).map(|k| luma([colour[0][k], colour[1][k], colour[2][k]])).collect();
|
||||
let mut edges = vec![0.0f32; px.len()];
|
||||
for (e, s) in edges.iter_mut().zip(sobel(&tones, w, h)) {
|
||||
*e = (s / 4.0).min(1.0);
|
||||
}
|
||||
let spacing = (0.35 * width).max(1.0);
|
||||
place.each(px, |x, y, p| {
|
||||
if p[3] == 0 {
|
||||
return;
|
||||
}
|
||||
let k = y * w + x;
|
||||
let c = [colour[0][k], colour[1][k], colour[2][k]];
|
||||
let gx = tone_at(&tones, w, h, x as isize + 1, y as isize) - tone_at(&tones, w, h, x as isize - 1, y as isize);
|
||||
let gy = tone_at(&tones, w, h, x as isize, y as isize + 1) - tone_at(&tones, w, h, x as isize, y as isize - 1);
|
||||
let angle = gy.atan2(gx) + std::f32::consts::FRAC_PI_2;
|
||||
let (dx, dy) = (angle.cos() as f64, angle.sin() as f64);
|
||||
let q = place.at(x, y);
|
||||
let along = q.x * dx + q.y * dy;
|
||||
let grain = value_noise(SALT_PENCIL, along / spacing, (q.x * 0.37 + q.y * 0.11) / spacing);
|
||||
let stroke = (0.5 + 0.5 * (along / spacing * TAU + grain * 3.0).sin()) as f32;
|
||||
let ink = pressure * (0.3 + 0.55 * stroke) * (0.55 + 0.45 * edges[k]);
|
||||
let lift = paper_lift * (1.0 - luma(c)) * 0.35;
|
||||
let c = c.map(|v| (v * (1.0 - ink * 0.45) + lift * (1.0 - v)).clamp(0.0, 1.0));
|
||||
*p = premultiply(c, f32::from(p[3]) / 255.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Cutout: the object as flat pieces of coloured paper. Its colours, softened as `simplicity`
|
||||
/// (0..10) asks and less as `fidelity` (1..3) keeps detail, fall into `levels` (2..8) steps per
|
||||
/// colour channel; each step's piece is painted in the average colour of what falls into it, so
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Photoshop-style raster effects (Effect › Artistic › Cutout, Dry Brush, Film Grain, Neon Glow, Paint Daubs, Plastic Wrap and
|
||||
//! Photoshop-style raster effects (Effect › Artistic › Colored Pencil, Cutout, Dry Brush, Film Grain, Neon Glow, Paint Daubs, Plastic Wrap and
|
||||
//! 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,
|
||||
@@ -44,7 +44,8 @@ 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; 52] = [
|
||||
pub const PIXEL_EFFECTS: [&str; 53] = [
|
||||
"artistic.coloredPencil",
|
||||
"artistic.cutout",
|
||||
"artistic.dryBrush",
|
||||
"artistic.filmGrain",
|
||||
@@ -103,6 +104,9 @@ pub const PIXEL_EFFECTS: [&str; 52] = [
|
||||
/// are in document units.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum PixelFx {
|
||||
/// Artistic › Colored Pencil: coloured strokes `width` (1..24) apart, as heavy as `pressure`
|
||||
/// (0..15), on paper lifted by `paper` (0..50).
|
||||
ColoredPencil { width: f64, pressure: f64, paper: f64 },
|
||||
/// Artistic › Cutout: flat pieces of colour in `levels` (2..8) steps per channel, their
|
||||
/// edges as simple as `simplicity` (0..10) and as faithful as `fidelity` (1..3) say.
|
||||
Cutout { levels: f64, simplicity: f64, fidelity: f64 },
|
||||
@@ -312,6 +316,11 @@ pub(crate) fn parse(id: &str, p: &Value) -> Option<PixelFx> {
|
||||
levels.iter().find(|(name, _)| name.eq_ignore_ascii_case(q)).map_or(default, |(_, v)| *v)
|
||||
};
|
||||
Some(match id {
|
||||
"artistic.coloredPencil" => PixelFx::ColoredPencil {
|
||||
width: num(p, "pencilWidth", 5.0).clamp(1.0, 24.0),
|
||||
pressure: num(p, "strokePressure", 5.0).clamp(0.0, 15.0),
|
||||
paper: num(p, "paperBrightness", 25.0).clamp(0.0, 50.0),
|
||||
},
|
||||
"artistic.cutout" => PixelFx::Cutout {
|
||||
levels: num(p, "levels", 4.0).round().clamp(2.0, 8.0),
|
||||
simplicity: num(p, "edgeSimplicity", 4.0).clamp(0.0, 10.0),
|
||||
@@ -600,6 +609,7 @@ impl PixelFx {
|
||||
// These three keep the object's coverage.
|
||||
PixelFx::SmudgeStick { .. } | PixelFx::Sponge { .. } | PixelFx::Watercolor { .. } => 0.0,
|
||||
PixelFx::FilmGrain { .. }
|
||||
| PixelFx::ColoredPencil { .. }
|
||||
| PixelFx::Cutout { .. }
|
||||
| PixelFx::DryBrush { .. }
|
||||
| PixelFx::NeonGlow { .. }
|
||||
@@ -658,6 +668,7 @@ impl PixelFx {
|
||||
// The cells around the pixel's, and the cells around theirs.
|
||||
PixelFx::ColorHalftone { max_radius, .. } => Some(3.0 * std::f64::consts::SQRT_2 * max_radius),
|
||||
PixelFx::Crystallize { cell } => Some(1.5 * cell),
|
||||
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::FilmGrain { .. }
|
||||
@@ -699,6 +710,7 @@ impl PixelFx {
|
||||
let Some(px) = pixels(data, w, h) else { return };
|
||||
let to_px = |len: f64| len / space.px.max(1e-9);
|
||||
match *self {
|
||||
PixelFx::ColoredPencil { width, pressure, paper } => artistic::colored_pencil(px, w, h, space, width, pressure, paper),
|
||||
PixelFx::Cutout { levels, simplicity, fidelity } => artistic::cutout(px, w, h, space, levels, simplicity, fidelity),
|
||||
PixelFx::DryBrush { size, detail, texture } => artistic::dry_brush(px, w, h, space, size, detail, texture),
|
||||
PixelFx::FilmGrain { grain, highlight, intensity } => artistic::film_grain(px, w, h, space, grain, highlight, intensity),
|
||||
|
||||
@@ -2421,6 +2421,12 @@ fn ramp(w: usize, h: usize) -> Vec<u8> {
|
||||
|
||||
#[test]
|
||||
fn artistic_params_take_defaults_and_stay_in_range() {
|
||||
assert_eq!(fx("artistic.coloredPencil", json!({})), PixelFx::ColoredPencil { width: 5.0, pressure: 5.0, paper: 25.0 });
|
||||
assert_eq!(
|
||||
fx("artistic.coloredPencil", json!({"pencilWidth": 0, "strokePressure": 200, "paperBrightness": -5})),
|
||||
PixelFx::ColoredPencil { width: 1.0, pressure: 15.0, paper: 0.0 }
|
||||
);
|
||||
assert_eq!(fx("artistic.coloredPencil", json!({})).reach(), Some(artistic::colored_pencil_reach(5.0)));
|
||||
assert_eq!(fx("artistic.cutout", json!({})), PixelFx::Cutout { levels: 4.0, simplicity: 4.0, fidelity: 2.0 });
|
||||
assert_eq!(
|
||||
fx("artistic.cutout", json!({"levels": 1e308, "edgeSimplicity": -5, "edgeFidelity": "NaN"})),
|
||||
@@ -2484,8 +2490,15 @@ fn artistic_params_take_defaults_and_stay_in_range() {
|
||||
fx("artistic.plasticWrap", json!({"highlightStrength": -1, "detail": 99, "smoothness": 0})),
|
||||
PixelFx::PlasticWrap { highlight: 0.0, detail: 15.0, smoothness: 1.0 }
|
||||
);
|
||||
for id in ["artistic.cutout", "artistic.dryBrush", "artistic.neonGlow", "artistic.plasticWrap", "artistic.posterEdges", "artistic.underpainting"]
|
||||
{
|
||||
for id in [
|
||||
"artistic.coloredPencil",
|
||||
"artistic.cutout",
|
||||
"artistic.dryBrush",
|
||||
"artistic.neonGlow",
|
||||
"artistic.plasticWrap",
|
||||
"artistic.posterEdges",
|
||||
"artistic.underpainting",
|
||||
] {
|
||||
assert_eq!(fx(id, json!({})).outset(Rect::new(0.0, 0.0, 40.0, 30.0)), 0.0, "{id} keeps the object's shape");
|
||||
}
|
||||
assert_eq!(fx("artistic.paintDaubs", json!({})), PixelFx::PaintDaubs { size: 10.0, sharpness: 25.0, kind: PaintDaubBrush::Simple });
|
||||
@@ -2509,6 +2522,19 @@ fn artistic_params_take_defaults_and_stay_in_range() {
|
||||
assert!(fx("artistic.roughPastels", json!({})).outset(Rect::new(0.0, 0.0, 40.0, 30.0)) > 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colored_pencil_strokes_change_pixels_and_keep_coverage() {
|
||||
let (w, h) = (48, 32);
|
||||
let src = ramp(w, h);
|
||||
let mut out = src.clone();
|
||||
fx("artistic.coloredPencil", json!({"strokePressure": 12})).apply(&mut out, w, h, &space(w, h));
|
||||
assert_ne!(out, src);
|
||||
assert!(out.as_chunks::<4>().0.iter().zip(src.as_chunks::<4>().0).all(|(o, s)| o[3] == s[3]));
|
||||
let mut mild = src.clone();
|
||||
fx("artistic.coloredPencil", json!({"strokePressure": 0, "paperBrightness": 0})).apply(&mut mild, w, h, &space(w, h));
|
||||
assert_eq!(mild, src, "zero pressure and paper leaves the art unchanged");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn artistic_filters_leave_invalid_coordinate_spaces_alone() {
|
||||
let (w, h) = (16, 12);
|
||||
|
||||
@@ -31,7 +31,8 @@ const BRUSH_STROKES: [(&str, &str); 8] = [
|
||||
];
|
||||
|
||||
/// Effect › Artistic, at their defaults.
|
||||
const ARTISTIC: [(&str, &str); 13] = [
|
||||
const ARTISTIC: [(&str, &str); 14] = [
|
||||
("artistic.coloredPencil", "{}"),
|
||||
("artistic.cutout", "{}"),
|
||||
("artistic.dryBrush", "{}"),
|
||||
("artistic.filmGrain", "{}"),
|
||||
|
||||
@@ -4557,6 +4557,8 @@ lighting Light Светлина
|
||||
Reset Ruler Origin Нулиране началото на линийката
|
||||
Artistic Художествени
|
||||
Film Grain… Филмова зърнистост…
|
||||
Colored Pencil… Цветен молив…
|
||||
Colored Pencil Цветен молив
|
||||
Cutout… Апликация…
|
||||
Cutout Апликация
|
||||
Dry Brush… Суха четка…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5056,6 +5056,8 @@ imageTrace Outline Obrys
|
||||
DWG (use DXF) DWG (použijte DXF)
|
||||
Artistic Umělecké
|
||||
Film Grain… Filmové zrno…
|
||||
Colored Pencil… Barevná tužka…
|
||||
Colored Pencil Barevná tužka
|
||||
Cutout… Výřez…
|
||||
Cutout Výřez
|
||||
Dry Brush… Suchý štětec…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5182,6 +5182,8 @@ swatch Bright Violet Kraftig violet
|
||||
Lock Variables Lås variabler
|
||||
Unlock Variables Lås variabler op
|
||||
Change to Artboard Rulers Skift til kunstpladelinealer
|
||||
Colored Pencil… Farveblyant…
|
||||
Colored Pencil Farveblyant
|
||||
Cutout… Udklip…
|
||||
Dry Brush… Tør pensel…
|
||||
Neon Glow… Neonglød…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4637,6 +4637,8 @@ lighting Light Licht
|
||||
Reset Ruler Origin Linealursprung zurücksetzen
|
||||
Artistic Kunstfilter
|
||||
Film Grain… Filmkörnung…
|
||||
Colored Pencil… Buntstift…
|
||||
Colored Pencil Buntstift
|
||||
Simple Einfach
|
||||
Light Rough Leicht rau
|
||||
Dark Rough Dunkel rau
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2266,6 +2266,8 @@ lighting Light Φως
|
||||
Left Diagonal Αριστερή διαγώνιος
|
||||
Artistic Καλλιτεχνικό
|
||||
Film Grain… Κόκκος φιλμ…
|
||||
Colored Pencil… Έγχρωμο μολύβι…
|
||||
Colored Pencil Έγχρωμο μολύβι
|
||||
Cutout… Αποκοπή…
|
||||
Cutout Αποκοπή
|
||||
Dry Brush… Ξηρό πινέλο…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2038 and column 19.
|
@@ -4644,6 +4644,8 @@ lighting Light Luz
|
||||
Reset Ruler Origin Restablecer el origen de las reglas
|
||||
Artistic Artístico
|
||||
Film Grain… Granulado de película…
|
||||
Colored Pencil… Lápiz de color…
|
||||
Colored Pencil Lápiz de color
|
||||
Cutout… Recorte…
|
||||
Cutout Recorte
|
||||
Dry Brush… Pincel seco…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4951,6 +4951,8 @@ imageTrace Outline Ääriviiva
|
||||
DWG (use DXF) DWG (käytä DXF:ää)
|
||||
Artistic Taiteelliset
|
||||
Film Grain… Filmin rakeisuus…
|
||||
Colored Pencil… Väriliitu…
|
||||
Colored Pencil Väriliitu
|
||||
Cutout… Leikkaus…
|
||||
Cutout Leikkaus
|
||||
Dry Brush… Kuiva sivellin…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4654,6 +4654,8 @@ lighting Light Lumière
|
||||
Reset Ruler Origin Réinitialiser l’origine des règles
|
||||
Artistic Artistique
|
||||
Film Grain… Grain photographique…
|
||||
Colored Pencil… Crayon de couleur…
|
||||
Colored Pencil Crayon de couleur
|
||||
Cutout… Découpage…
|
||||
Cutout Découpage
|
||||
Dry Brush… Pinceau sec…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1587,6 +1587,8 @@ file-filter Templates Sablonok
|
||||
Select Segments Szakaszok kijelölése
|
||||
Artistic Művészi
|
||||
Film Grain… Filmszemcse…
|
||||
Colored Pencil… Színes ceruza…
|
||||
Colored Pencil Színes ceruza
|
||||
Cutout… Kivágás…
|
||||
Cutout Kivágás
|
||||
Dry Brush… Száraz ecset…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5182,6 +5182,8 @@ swatch Bright Violet Violet cerah
|
||||
Lock Variables Kunci variabel
|
||||
Unlock Variables Buka kunci variabel
|
||||
Change to Artboard Rulers Ubah ke penggaris artboard
|
||||
Colored Pencil… Pensil warna…
|
||||
Colored Pencil Pensil warna
|
||||
Cutout… Potongan…
|
||||
Dry Brush… Kuas kering…
|
||||
Neon Glow… Pendar neon…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3808 and column 19.
|
@@ -4686,6 +4686,8 @@ lighting Light Luce
|
||||
Reset Ruler Origin Ripristina origine dei righelli
|
||||
Artistic Artistico
|
||||
Film Grain… Grana della pellicola…
|
||||
Colored Pencil… Matita colorata…
|
||||
Colored Pencil Matita colorata
|
||||
Cutout… Ritaglio…
|
||||
Cutout Ritaglio
|
||||
Dry Brush… Pennello secco…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4725,6 +4725,8 @@ lighting Light ライト
|
||||
Reset Ruler Origin 定規の原点をリセット
|
||||
Artistic アーティスティック
|
||||
Film Grain… フィルム粒子…
|
||||
Colored Pencil… 色鉛筆…
|
||||
Colored Pencil 色鉛筆
|
||||
Cutout… カットアウト…
|
||||
Cutout カットアウト
|
||||
Dry Brush… ドライブラシ…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5018,6 +5018,8 @@ imageTrace Outline კონტური
|
||||
Create Slice from Selection ნაჭრის შექმნა მონიშნულიდან
|
||||
Create Slices from Guides ნაჭრების შექმნა დამხმარე ხაზებიდან
|
||||
Cutout აპლიკაცია
|
||||
Colored Pencil… ფერადი ფანქარი…
|
||||
Colored Pencil ფერადი ფანქარი
|
||||
Dry Brush მშრალი ფერწანი
|
||||
Cutout… აპლიკაცია…
|
||||
Dry Brush… მშრალი ფერწანი…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4649,6 +4649,8 @@ lighting Light 광원
|
||||
X11 (XWayland) X11 (XWayland)
|
||||
Artistic 예술 효과
|
||||
Film Grain… 필름 그레인…
|
||||
Colored Pencil… 색연필…
|
||||
Colored Pencil 색연필
|
||||
Cutout… 오려내기…
|
||||
Cutout 오려내기
|
||||
Dry Brush… 드라이 브러시…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5193,6 +5193,8 @@ swatch Bright Violet Felviolet
|
||||
Lock Variables Variabelen vergrendelen
|
||||
Unlock Variables Variabelen ontgrendelen
|
||||
Change to Artboard Rulers Wijzigen in tekenbordlinialen
|
||||
Colored Pencil… Gekleurd potlood…
|
||||
Colored Pencil Gekleurd potlood
|
||||
Cutout… Knipsel…
|
||||
Dry Brush… Droog penseel…
|
||||
Neon Glow… Neongloed…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4889,6 +4889,8 @@ imageTrace Outline Kontur
|
||||
DWG (use DXF) DWG (użyj DXF)
|
||||
Artistic Artystyczne
|
||||
Film Grain… Ziarno filmu…
|
||||
Colored Pencil… Kolorowa kredka…
|
||||
Colored Pencil Kolorowa kredka
|
||||
Cutout… Wycinanka…
|
||||
Cutout Wycinanka
|
||||
Dry Brush… Suchy pędzel…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4039,6 +4039,8 @@ axis Both Ambos
|
||||
Reset Ruler Origin Redefinir origem das réguas
|
||||
Artistic Artístico
|
||||
Film Grain… Granulação de filme…
|
||||
Colored Pencil… Lápis de cor…
|
||||
Colored Pencil Lápis de cor
|
||||
Cutout… Recorte…
|
||||
Cutout Recorte
|
||||
Dry Brush… Pincel seco…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4682,6 +4682,8 @@ lighting Light Свет
|
||||
Reset Ruler Origin Сбросить начало координат линеек
|
||||
Artistic Художественные
|
||||
Film Grain… Зернистость плёнки…
|
||||
Colored Pencil… Цветной карандаш…
|
||||
Colored Pencil Цветной карандаш
|
||||
Cutout… Аппликация…
|
||||
Cutout Аппликация
|
||||
Dry Brush… Сухая кисть…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4563,6 +4563,8 @@ lighting Light Ljus
|
||||
Reset Ruler Origin Återställ linjalens origo
|
||||
Artistic Konstnärligt
|
||||
Film Grain… Filmkorn…
|
||||
Colored Pencil… Färgpenna…
|
||||
Colored Pencil Färgpenna
|
||||
Cutout… Urklipp…
|
||||
Cutout Urklipp
|
||||
Dry Brush… Torr pensel…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4666,6 +4666,8 @@ lighting Light Світло
|
||||
Reset Ruler Origin Скинути початок координат лінійок
|
||||
Artistic Художні
|
||||
Film Grain… Зернистість плівки…
|
||||
Colored Pencil… Кольоровий олівець…
|
||||
Colored Pencil Кольоровий олівець
|
||||
Cutout… Аплікація…
|
||||
Cutout Аплікація
|
||||
Dry Brush… Суха кисть…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 733 and column 40.
|
@@ -1268,6 +1268,8 @@
|
||||
Fill: click for swatches, Shift-click for the color mixer Tô: bấm để xem mẫu màu, Shift-bấm để trộn màu
|
||||
Fills Vùng tô
|
||||
Film Grain… Hạt phim…
|
||||
Colored Pencil… Bút chì màu…
|
||||
Colored Pencil Bút chì màu
|
||||
Cutout… Cắt dán…
|
||||
Cutout Cắt dán
|
||||
Dry Brush… Cọ khô…
|
||||
|
||||
|
@@ -4950,6 +4950,8 @@ lighting Light 光源
|
||||
Reset Ruler Origin 重置标尺原点
|
||||
Artistic 艺术效果
|
||||
Film Grain… 胶片颗粒…
|
||||
Colored Pencil… 彩色铅笔…
|
||||
Colored Pencil 彩色铅笔
|
||||
Cutout… 剪纸…
|
||||
Dry Brush… 干画笔…
|
||||
Cutout 剪纸
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4756,6 +4756,8 @@ lighting Light 光源
|
||||
Reset Ruler Origin 重設尺標原點
|
||||
Artistic 藝術效果
|
||||
Film Grain… 底片顆粒…
|
||||
Colored Pencil… 彩色鉛筆…
|
||||
Colored Pencil 彩色鉛筆
|
||||
Cutout… 剪紙…
|
||||
Dry Brush… 乾畫筆…
|
||||
Cutout 剪紙
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -89,6 +89,7 @@ fn effect_menu_lists_the_artistic_filters_before_blur() {
|
||||
assert_eq!(
|
||||
labels,
|
||||
[
|
||||
"Colored Pencil…",
|
||||
"Cutout…",
|
||||
"Dry Brush…",
|
||||
"Film Grain…",
|
||||
@@ -105,8 +106,8 @@ fn effect_menu_lists_the_artistic_filters_before_blur() {
|
||||
]
|
||||
);
|
||||
assert!(artistic.iter().all(|e| e.command.as_deref() == Some("effect.dialog")));
|
||||
assert_eq!(artistic[1].params, json!({"effect": "artistic.dryBrush"}));
|
||||
assert_eq!(artistic[3].params, json!({"effect": "artistic.neonGlow"}));
|
||||
assert_eq!(artistic[2].params, json!({"effect": "artistic.dryBrush"}));
|
||||
assert_eq!(artistic[4].params, json!({"effect": "artistic.neonGlow"}));
|
||||
let at = |name: &str| entries.iter().position(|e| e.path == ["Effect", name]).unwrap();
|
||||
assert!(at("Artistic") < at("Blur"));
|
||||
}
|
||||
|
||||
@@ -12,6 +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 | 49 | 86% | 7–12 |
|
||||
| Photoshop effects (raster, Effect Gallery) | 57 | 48 | 84% | 8–14 |
|
||||
| 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 | — | — |
|
||||
@@ -38,6 +39,7 @@ its resolution, PDF export warns once per object with the requested and the lowe
|
||||
|
||||
| Submenu | Items | Ours | Missing |
|
||||
|---|---|---:|---|
|
||||
| Artistic | Colored Pencil, Cutout, Dry Brush, Film Grain, Fresco, Neon Glow, Paint Daubs, Palette Knife, Plastic Wrap, Poster Edges, Rough Pastels, Smudge Stick, Sponge, Underpainting, Watercolor | 10/15 (approximate Colored Pencil, Cutout, Dry Brush, Film Grain, Neon Glow, Plastic Wrap, Poster Edges, Smudge Stick, Sponge, Watercolor) | Fresco, Paint Daubs, Palette Knife, Rough Pastels, Underpainting |
|
||||
| Artistic | Colored Pencil, Cutout, Dry Brush, Film Grain, Fresco, Neon Glow, Paint Daubs, Palette Knife, Plastic Wrap, Poster Edges, Rough Pastels, Smudge Stick, Sponge, Underpainting, Watercolor | 9/15 (approximate Cutout, Film Grain, Neon Glow, Paint Daubs, Plastic Wrap, Poster Edges, Smudge Stick, Sponge, Watercolor) | Colored Pencil, Dry Brush, Fresco, Palette Knife, Rough Pastels, Underpainting |
|
||||
| Blur | Gaussian Blur, Radial Blur, Smart Blur | 3/3 | — |
|
||||
| Brush Strokes | Accented Edges, Angled Strokes, Crosshatch, Dark Strokes, Ink Outlines, Spatter, Sprayed Strokes, Sumi-e | 8/8 | — |
|
||||
@@ -52,7 +54,7 @@ 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 12 missing filters are ~8–14 h and the Effect
|
||||
(see [calibration](target-app-parity.md#calibration)), so the 10 missing filters are ~7–12 h and the Effect
|
||||
Gallery dialog another 4–6 h. These parallelize well across agents.
|
||||
|
||||
Film Grain (`artistic.filmGrain`, Effect › Artistic) adds stable monochrome noise to shadows and
|
||||
|
||||
+4
-5
@@ -234,12 +234,11 @@ from G14 and the budget run of G15: **~170–270 h** one agent, ~50–80 h wall
|
||||
## G2 Photoshop-style raster effects and the Effect Gallery
|
||||
|
||||
- **Done:** Effect › Texture › Texturizer › Load Texture… (stored grayscale `textureImage`, Loaded Texture in the Texture menu), matching Glass.
|
||||
- **Missing:** 24 of 57 filters (the remaining 11 Artistic filters and 13 of Sketch's 14), the Effect Gallery dialog. Measured in
|
||||
- **Missing:** 10 of 57 filters (7 Artistic, 2 Sketch and 1 more), the Effect Gallery dialog, Load
|
||||
Texture for Texturizer. Measured in
|
||||
- **Missing:** 8 of 57 filters (5 Artistic, 2 Sketch and 1 more), the Effect Gallery dialog. Measured in
|
||||
[effects-parity.md](effects-parity.md).
|
||||
- **Done:** the pixel-filter pipeline and 45 filters (Artistic: Cutout, Film Grain, Neon Glow, Plastic Wrap, Poster Edges, Smudge Stick, Sponge, Watercolor; Blur, Brush Strokes, Distort, Pixelate, Sharpen; Sketch:
|
||||
Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Graphic Pen, Halftone Pattern, Photocopy, Plaster, Reticulation, Stamp; Stylize, Texture, Video), with live preview and editable native settings. Smart Blur supports Edge Only and Overlay Edge
|
||||
- **Done:** Effect › Artistic › Colored Pencil (`artistic.coloredPencil`, pencil width, stroke pressure, paper brightness; original visual approximation).
|
||||
- **Done:** the pixel-filter pipeline and 49 filters (Artistic: Colored Pencil, Cutout, Dry Brush, Film Grain, Neon Glow, Plastic Wrap, Poster Edges, Smudge Stick, Sponge, Watercolor; Blur, Brush Strokes, Distort, Pixelate, Sharpen; Sketch:
|
||||
Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Water Paper; Stylize, Texture, Video), with live preview and editable native settings. Smart Blur supports Edge Only and Overlay Edge
|
||||
modes.
|
||||
- **Estimate:** 8–14 h (measured 0.7–1.2 h per filter); parallelizes well.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user