G2: Effect › Artistic › Paint Daubs raster filter

Squashed from #3032 onto main.
This commit is contained in:
bflatastic
2026-10-22 00:23:49 +07:00
parent f329f6271d
commit 03bd5e5a53
33 changed files with 419 additions and 10 deletions
+7
View File
@@ -378,6 +378,13 @@ pub fn effect_catalog() -> Vec<EffectInfo> {
"{glowSize: -24..24 (5; above 0 the light areas glow, below 0 the dark ones; farther from 0 spreads the glow wider), glowBrightness: 0..50 (15; a stronger glow over dimmer greys), color: \"#rrggbb\" (\"#4da6ff\"; the glow's colour)} redraws the object in greys lit by a coloured glow, keeping its coverage. Original visual approximation; chosen VectorCraft defaults.",
json!({"glowSize": 5.0, "glowBrightness": 15.0, "color": "#4da6ff"}),
),
r(
"artistic.paintDaubs",
"Paint Daubs…",
ARTISTIC,
"{brushSize: 1..50 (10; dab centres farther apart), sharpness: 0..40 (25; harder dab edges), brushType: \"simple\"|\"lightRough\"|\"darkRough\"|\"wideSharp\"|\"wideBlurry\"|\"sparkle\" (\"simple\")} repaints the object with thick round brush dabs in the local colours, keeping its coverage. Original visual approximation; chosen VectorCraft defaults.",
json!({"brushSize": 10.0, "sharpness": 25.0, "brushType": "simple"}),
),
r(
"artistic.paletteKnife",
"Palette Knife…",
+131 -4
View File
@@ -1,5 +1,5 @@
//! Effect › Artistic (Cutout, Dry Brush, Film Grain, Neon Glow, Palette Knife, Plastic Wrap, Poster Edges, Smudge Stick, Sponge and
//! Watercolor). Original filters built from
//! Effect › Artistic (Cutout, Dry Brush, Film Grain, Neon Glow, Paint Daubs, Palette Knife, Plastic Wrap, Poster
//! Edges, Smudge Stick, Sponge and Watercolor). Original filters built from
//! public behaviour documentation:
//! <https://helpx.adobe.com/illustrator/using/summary-effects.html> and
//! <https://helpx.adobe.com/photoshop-elements/using/artistic-filters.html>.
@@ -9,9 +9,9 @@ use std::f64::consts::TAU;
use super::brushstrokes::{Smear, mix, stroke_reach, unit, unpremultiply};
use super::edges::sobel;
use super::pixelate::{Place, cell, rand, value_noise};
use super::pixelate::{Around, Place, Soft, cell, point_in, rand, value_noise};
use super::texture::{luma, premultiply, straight};
use super::{PixelSpace, blur_plane};
use super::{PixelSpace, blur_plane, pick};
use vectorcraft_geom::{Point, Vec2};
const SALT_DRY: u64 = 264;
@@ -19,6 +19,56 @@ const MARGIN: f64 = 1.0;
const SALT_PLASTIC: u64 = 512;
const SALT_FILM: u64 = 256;
const SALT_DAUB: u64 = 272;
/// Paint Daubs' brush types, in the Brush Type menu's order: (label, parameter value).
/// Illustrator's list: <https://helpx.adobe.com/illustrator/using/filter-effects.html#paint_daubs>.
pub const PAINT_DAUB_BRUSH_TYPES: [(&str, &str); 6] = [
("Simple", "simple"),
("Light Rough", "lightRough"),
("Dark Rough", "darkRough"),
("Wide Sharp", "wideSharp"),
("Wide Blurry", "wideBlurry"),
("Sparkle", "sparkle"),
];
/// A Paint Daubs brush ([`PAINT_DAUB_BRUSH_TYPES`]).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PaintDaubBrush {
Simple,
LightRough,
DarkRough,
WideSharp,
WideBlurry,
Sparkle,
}
impl PaintDaubBrush {
const ALL: [PaintDaubBrush; 6] = [
PaintDaubBrush::Simple,
PaintDaubBrush::LightRough,
PaintDaubBrush::DarkRough,
PaintDaubBrush::WideSharp,
PaintDaubBrush::WideBlurry,
PaintDaubBrush::Sparkle,
];
/// The brush of Brush Type `value` (a [`PAINT_DAUB_BRUSH_TYPES`] value, any case); Simple otherwise.
pub fn parse(value: &str) -> Self {
if value.eq_ignore_ascii_case("wideRough") {
return PaintDaubBrush::WideSharp;
}
if value.eq_ignore_ascii_case("hue") {
return PaintDaubBrush::WideBlurry;
}
pick(&PAINT_DAUB_BRUSH_TYPES, &Self::ALL, value, PaintDaubBrush::Simple)
}
}
/// How far (document units) a dab reaches past its centre at `size` (1..50).
pub(super) fn paint_daub_radius(size: f64) -> f64 {
size.clamp(1.0, 50.0) * 0.48
}
/// 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.
@@ -247,6 +297,83 @@ pub(super) fn poster_edges(px: &mut [[u8; 4]], w: usize, h: usize, space: &Pixel
}
}
/// Paint Daubs: thick round dabs on a grid `size` (1..50) points apart, each dab painted in the
/// local colour around its centre, with edges as sharp as `sharpness` (0..40) and a profile from
/// `kind`. Coverage is kept.
pub(super) fn paint_daubs(px: &mut [[u8; 4]], w: usize, h: usize, space: &PixelSpace, size: f64, sharpness: f64, kind: PaintDaubBrush) {
if !([size, sharpness].iter().all(|v| v.is_finite()) && size > 0.0) {
return;
}
let Some(place) = Place::new(space, w, h) else { return };
let spacing = size.clamp(1.0, 50.0);
let brush_r = paint_daub_radius(size);
let edge = 1.0 + 2.5 * (sharpness.clamp(0.0, 40.0) / 40.0);
let soft = Soft::new(px, w, (spacing * 0.15) / place.px);
let dab = |i: i64, j: i64| {
let at = point_in(SALT_DAUB, i, j);
let center = Point::new(at.x * spacing, at.y * spacing);
(center, soft.at(place.index(center)))
};
let cover = |q: Point, center: Point, colour: [f32; 4]| -> f32 {
if colour[3] <= 0.0 {
return 0.0;
}
let (dx, dy) = (q.x - center.x, q.y - center.y);
let (dx, dy) = match kind {
PaintDaubBrush::WideSharp | PaintDaubBrush::WideBlurry => (dx * 0.65, dy * 1.35),
_ => (dx, dy),
};
let t = (dx.hypot(dy) / brush_r).clamp(0.0, 1.0);
let edge_k = match kind {
PaintDaubBrush::WideSharp => edge * 1.35,
PaintDaubBrush::WideBlurry => edge * 0.55,
_ => edge,
};
let mut c = (1.0 - t).powf(edge_k) as f32;
let tone = luma(unpremultiply(colour).0);
match kind {
PaintDaubBrush::LightRough => c *= 0.7 + 0.35 * rough_bristle(q, 0),
PaintDaubBrush::DarkRough => c *= 0.55 + 0.45 * (1.0 - rough_bristle(q, 1)),
PaintDaubBrush::Sparkle if rough_bristle(center, 2) > 0.92 && tone > 0.55 => c = c.max(0.85),
PaintDaubBrush::Simple | PaintDaubBrush::WideSharp | PaintDaubBrush::WideBlurry | PaintDaubBrush::Sparkle => {}
}
c
};
let mut around = Around::new();
place.each(px, |x, y, out| {
if out[3] == 0 {
return;
}
let q = place.at(x, y);
let (u, v) = (q.x / spacing, q.y / spacing);
let (Some(i), Some(j)) = (cell(u), cell(v)) else { return };
let mut sum = [0.0f32; 3];
let mut weight = 0.0f32;
for k in 0..9 {
let Some((center, colour)) = around.get((i, j), k, dab) else { continue };
let w = cover(q, center, colour);
if w <= 0.0 {
continue;
}
let c = unpremultiply(colour).0;
for (s, v) in sum.iter_mut().zip(c) {
*s += v * w;
}
weight += w;
}
if weight <= 1e-6 {
return;
}
let c = sum.map(|v| (v / weight).clamp(0.0, 1.0));
*out = premultiply(c, f32::from(out[3]) / 255.0);
});
}
fn rough_bristle(p: Point, k: u64) -> f32 {
let (Some(i), Some(j)) = (cell(p.x * 3.7), cell(p.y * 3.7)) else { return 0.5 };
rand(SALT_DAUB + 3, i, j, k) as f32
}
/// How far (document units) Plastic Wrap's softened relief is sampled at `smoothness` (1..15).
pub(super) fn plastic_reach(smoothness: f64) -> f64 {
3.0 * (0.15 + 0.35 * smoothness.clamp(1.0, 15.0))
+15 -2
View File
@@ -1,4 +1,4 @@
//! Photoshop-style raster effects (Effect › Artistic › Cutout, Dry Brush, Film Grain, Neon Glow, Plastic Wrap and
//! Photoshop-style raster effects (Effect › Artistic › Cutout, Dry Brush, Film Grain, Neon Glow, Paint Daubs, Plastic Wrap and
//! Poster Edges, 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,
@@ -34,6 +34,7 @@ use vectorcraft_geom::{Affine, Point, Rect};
use crate::util::{flag, num, text};
pub use artistic::{PAINT_DAUB_BRUSH_TYPES, PaintDaubBrush};
pub use blur::{SMART_BLUR_MODES, SmartBlurMode};
pub use brushstrokes::{STROKE_DIRECTIONS, StrokeDirection};
pub use distort::{GLASS_TEXTURES, GLASS_TEXTURES_LOADED, GlassTexture};
@@ -43,11 +44,12 @@ 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; 49] = [
pub const PIXEL_EFFECTS: [&str; 50] = [
"artistic.cutout",
"artistic.dryBrush",
"artistic.filmGrain",
"artistic.neonGlow",
"artistic.paintDaubs",
"artistic.paletteKnife",
"artistic.plasticWrap",
"artistic.posterEdges",
@@ -123,6 +125,9 @@ pub enum PixelFx {
/// light areas (`size` above 0) or the dark ones (below 0), spread by |`size`| (-24..24), as
/// strong as `brightness` (0..50).
NeonGlow { size: f64, brightness: f64, colour: [f32; 3] },
/// Artistic › Paint Daubs: dabs `size` (1..50) points apart, as sharp as `sharpness` (0..40),
/// with brush `kind`.
PaintDaubs { size: f64, sharpness: f64, kind: PaintDaubBrush },
/// Artistic › Palette Knife: knife strokes `stroke_size` (1..50) long smear the colours;
/// `stroke_detail` (1..3) keeps more original detail when higher; `softness` (0..10) softens
/// the strokes.
@@ -342,6 +347,11 @@ pub(crate) fn parse(id: &str, p: &Value) -> Option<PixelFx> {
shadow: num(p, "shadowIntensity", 1.0).clamp(0.0, 10.0),
texture: num(p, "texture", 1.0).clamp(1.0, 3.0).round() as u32,
},
"artistic.paintDaubs" => PixelFx::PaintDaubs {
size: num(p, "brushSize", 10.0).clamp(1.0, 50.0),
sharpness: num(p, "sharpness", 25.0).clamp(0.0, 40.0),
kind: PaintDaubBrush::parse(text(p, "brushType", "simple")),
},
"artistic.plasticWrap" => PixelFx::PlasticWrap {
highlight: num(p, "highlightStrength", 20.0).clamp(0.0, 20.0),
detail: num(p, "detail", 12.0).clamp(0.0, 15.0),
@@ -557,6 +567,7 @@ impl PixelFx {
PixelFx::BasRelief { .. } | PixelFx::Charcoal { .. } | PixelFx::Photocopy { .. } | PixelFx::Stamp { .. } => 0.0,
PixelFx::WaterPaper { fiber_length, .. } => sketch::water_paper_shift(fiber_length),
PixelFx::GlowingEdges { width, smoothness, .. } => width.max(smoothness * 3.0),
PixelFx::PaintDaubs { size, .. } => artistic::paint_daub_radius(size),
// These three keep the object's coverage.
PixelFx::SmudgeStick { .. } | PixelFx::Sponge { .. } | PixelFx::Watercolor { .. } => 0.0,
PixelFx::FilmGrain { .. }
@@ -625,6 +636,7 @@ impl PixelFx {
| PixelFx::Reticulation { .. } => Some(0.0),
PixelFx::DryBrush { size, detail, .. } => Some(artistic::dry_brush_reach(size, detail)),
PixelFx::Plaster { smoothness, .. } => Some(sketch::plaster_reach(smoothness)),
PixelFx::PaintDaubs { size, .. } => Some(artistic::paint_daub_radius(size) + size * 0.15),
PixelFx::WaterPaper { fiber_length, .. } => {
Some(sketch::water_paper_shift(fiber_length) + 3.0 * (0.06 * fiber_length.clamp(3.0, 50.0)).max(0.35))
}
@@ -661,6 +673,7 @@ impl PixelFx {
PixelFx::SmudgeStick { stroke, highlight, intensity } => paint::smudge_stick(px, w, h, space, stroke, highlight, intensity),
PixelFx::Sponge { brush, definition, smoothness } => paint::sponge(px, w, h, space, brush, definition, smoothness),
PixelFx::Watercolor { detail, shadow, texture } => paint::watercolor(px, w, h, space, detail, shadow, texture),
PixelFx::PaintDaubs { size, sharpness, kind } => artistic::paint_daubs(px, w, h, space, size, sharpness, kind),
PixelFx::PlasticWrap { highlight, detail, smoothness } => artistic::plastic_wrap(px, w, h, space, highlight, detail, smoothness),
PixelFx::NeonGlow { size, brightness, colour } => artistic::neon_glow(px, w, h, space, size, brightness, colour),
PixelFx::PaletteKnife { stroke_size, stroke_detail, softness } => {
+30
View File
@@ -2449,6 +2449,14 @@ fn artistic_params_take_defaults_and_stay_in_range() {
for id in ["artistic.cutout", "artistic.dryBrush", "artistic.neonGlow", "artistic.plasticWrap", "artistic.posterEdges"] {
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 });
assert_eq!(
fx("artistic.paintDaubs", json!({"brushSize": 0, "sharpness": 99, "brushType": "wideBlurry"})),
PixelFx::PaintDaubs { size: 1.0, sharpness: 40.0, kind: PaintDaubBrush::WideBlurry }
);
let doc = crate::effect_info("artistic.paintDaubs").unwrap().params;
assert!(PAINT_DAUB_BRUSH_TYPES.iter().all(|(_, v)| doc.contains(&format!("\"{v}\""))), "{doc}");
assert!(fx("artistic.paintDaubs", json!({})).outset(Rect::new(0.0, 0.0, 40.0, 30.0)) > 0.0);
}
#[test]
@@ -2543,6 +2551,28 @@ fn cutout_simplicity_smooths_the_pieces_edges() {
assert!(changes(10.0) * 4 < changes(0.0), "{} vs {}", changes(10.0), changes(0.0));
}
#[test]
fn paint_daubs_coarsens_a_ramp_and_keeps_coverage() {
let (w, h) = (64, 32);
let src = ramp(w, h);
let mut out = src.clone();
fx("artistic.paintDaubs", json!({"brushSize": 28, "sharpness": 35})).apply(&mut out, w, h, &space(w, h));
assert_ne!(out, src, "dabbed art differs from the ramp");
assert!(out.as_chunks::<4>().0.iter().zip(src.as_chunks::<4>().0).all(|(o, s)| o[3] == s[3]));
}
#[test]
fn paint_daubs_larger_brushes_flatten_more() {
let (w, h) = (80, 40);
let src = ramp(w, h);
let dab_colours = |size: f64| {
let mut out = src.clone();
fx("artistic.paintDaubs", json!({"brushSize": size, "sharpness": 20})).apply(&mut out, w, h, &space(w, h));
colours(&out).len()
};
assert!(dab_colours(35.0) < dab_colours(8.0), "{} vs {}", dab_colours(35.0), dab_colours(8.0));
}
#[test]
fn poster_edges_draw_black_lines_on_edges_and_posterize_the_rest() {
let (w, h) = (40, 20);
+3 -1
View File
@@ -31,11 +31,13 @@ const BRUSH_STROKES: [(&str, &str); 8] = [
];
/// Effect › Artistic, at their defaults.
const ARTISTIC: [(&str, &str); 10] = [
const ARTISTIC: [(&str, &str); 11] = [
("artistic.cutout", "{}"),
("artistic.dryBrush", "{}"),
("artistic.filmGrain", "{}"),
("artistic.neonGlow", "{}"),
// Wide Blurry softens dabs; Simple leaves uniform fills unchanged on the striped art.
("artistic.paintDaubs", r#"{"brushType": "wideBlurry"}"#),
("artistic.paletteKnife", "{}"),
("artistic.plasticWrap", "{}"),
("artistic.posterEdges", "{}"),
+6
View File
@@ -201,6 +201,10 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
pub(crate) const FILM_GRAIN_FIELDS: [(&str, &str, f64); 3] =
[("grain", "Grain", 20.0), ("highlightArea", "Highlight Area", 20.0), ("intensity", "Intensity", 10.0)];
/// Paint Daubs › Brush Type labels ([`vectorcraft_effects::pixel::PAINT_DAUB_BRUSH_TYPES`]); extend
/// [`crate::menus::menu_strings`] with these like [`FILM_GRAIN_FIELDS`].
pub(crate) const PAINT_DAUB_BRUSH_TYPE_LABELS: [&str; 6] = ["Simple", "Light Rough", "Dark Rough", "Wide Sharp", "Wide Blurry", "Sparkle"];
fn film_grain_fields(ui: &mut egui::Ui, d: &mut Dialog) -> bool {
let before = d.fields.clone();
// Use one column wide enough for this language's longest label, keeping every rail aligned.
@@ -292,6 +296,7 @@ fn choices(effect: &str, key: &str) -> Option<form::Choices> {
("brushStrokes.sprayedStrokes", "strokeDirection") => Some(&vectorcraft_effects::pixel::STROKE_DIRECTIONS),
("distort.glass", "texture") => Some(&vectorcraft_effects::pixel::GLASS_TEXTURES),
("pixelate.mezzotint", "type") => Some(&vectorcraft_effects::pixel::MEZZOTINT_TYPES),
("artistic.paintDaubs", "brushType") => Some(&vectorcraft_effects::pixel::PAINT_DAUB_BRUSH_TYPES),
("sketch.graphicPen", "strokeDirection") => Some(&vectorcraft_effects::pixel::STROKE_DIRECTIONS),
("sketch.halftonePattern", "patternType") => Some(&vectorcraft_effects::pixel::HALFTONE_TYPES),
("sketch.plaster", "lightDirection") => Some(&vectorcraft_effects::pixel::LIGHT_DIRECTIONS),
@@ -714,6 +719,7 @@ mod tests {
("distort.roughen", "points"),
("stylize.innerGlow", "source"),
(DROP_SHADOW, "shade"),
("artistic.paintDaubs", "brushType"),
] {
let doc = vectorcraft_effects::effect_info(effect).unwrap().params;
let listed = doc.split(&format!("{key}: ")).nth(1).unwrap().split([',', '}', ' ']).next().unwrap().to_string();
+1 -1
View File
@@ -115,7 +115,7 @@ use serde_json::{Value, json};
pub use color_picker::open as open_color_picker;
pub use document_setup::open as open_document_setup;
pub use effect::open as open_effect_dialog;
pub(crate) use effect::{FILM_GRAIN_FIELDS, SHADES, shown_choices};
pub(crate) use effect::{FILM_GRAIN_FIELDS, PAINT_DAUB_BRUSH_TYPE_LABELS, SHADES, shown_choices};
pub use export_as::open as open_export_as;
pub use export_for_screens::open as open_export_for_screens;
pub(crate) use export_for_screens::{
+9
View File
@@ -32,6 +32,13 @@
Channel 4 Канал 4
Cell Size Размер на клетката
Fine Dots Финни точки
Simple Прост
Light Rough Светъл груб
Dark Rough Тъмен груб
Wide Sharp Широк остър
Wide Blurry Широк размазан
Sparkle Блясък
Medium Dots Средни точки
Grainy Dots Зърнести точки
Coarse Dots Едри точки
@@ -4557,6 +4564,8 @@ lighting Light Светлина
Neon Glow… Неоново сияние…
Palette Knife… Нож за палитра…
Neon Glow Неоново сияние
Paint Daubs… Мазки с боя…
Paint Daubs Мазки с боя
Palette Knife Нож за палитра
Poster Edges… Плакатни ръбове…
Poster Edges Плакатни ръбове
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2915,6 +2915,13 @@ lighting Light Světlo
Soft Light Měkké světlo
Crosshatch Křížové šrafování
Fine Dots Jemné tečky
Simple Jednoduchý
Light Rough Světle hrubý
Dark Rough Tmavě hrubý
Wide Sharp Široce ostrý
Wide Blurry Široce rozmazaný
Sparkle Jiskra
Medium Dots Střední tečky
Grainy Dots Zrnité tečky
Coarse Dots Hrubé tečky
@@ -5056,6 +5063,8 @@ imageTrace Outline Obrys
Neon Glow… Neonová záře…
Palette Knife… Špachtle…
Neon Glow Neonová záře
Paint Daubs… Malířské tahy…
Paint Daubs Malířské tahy
Palette Knife Špachtle
Poster Edges… Plakátové okraje…
Poster Edges Plakátové okraje
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2688,6 +2688,13 @@ lighting Light Lys
Soft Light Blødt lys
Crosshatch Krydsskravering
Fine Dots Fine prikker
Simple Enkel
Light Rough Lys ru
Dark Rough Mørk ru
Wide Sharp Bred skarp
Wide Blurry Bred sløret
Sparkle Glimt
Medium Dots Mellemstore prikker
Grainy Dots Kornede prikker
Coarse Dots Grove prikker
@@ -5183,6 +5190,8 @@ swatch Bright Violet Kraftig violet
Cutout Udklip
Dry Brush Tør pensel
Neon Glow Neonglød
Paint Daubs… Malerklatter…
Paint Daubs Malerklatter
Palette Knife Paletkniv
Poster Edges Plakatkanter
Apply Data Set Anvend datasæt
Can't render this file because it contains an unexpected character in line 2 and column 73.
+8
View File
@@ -4637,6 +4637,12 @@ lighting Light Licht
Reset Ruler Origin Linealursprung zurücksetzen
Artistic Kunstfilter
Film Grain… Filmkörnung…
Simple Einfach
Light Rough Leicht rau
Dark Rough Dunkel rau
Wide Sharp Breit scharf
Wide Blurry Breit unscharf
Sparkle Funkeln
Cutout… Ausschnitt…
Cutout Ausschnitt
Dry Brush… Trockenpinsel…
@@ -4644,6 +4650,8 @@ lighting Light Licht
Neon Glow… Neonglühen…
Palette Knife… Palettenmesser…
Neon Glow Neonglühen
Paint Daubs… Tupfer…
Paint Daubs Tupfer
Palette Knife Palettenmesser
Poster Edges… Posterkanten…
Poster Edges Posterkanten
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -29,6 +29,13 @@
Channel 4 Κανάλι 4
Cell Size Μέγεθος κελιού
Fine Dots Λεπτές κουκκίδες
Simple Απλό
Light Rough Ελαφρύ τραχύ
Dark Rough Σκούρο τραχύ
Wide Sharp Ευρύ οξύ
Wide Blurry Ευρύ θολό
Sparkle Λάμψη
Medium Dots Μεσαίες κουκκίδες
Grainy Dots Κοκκώδεις κουκκίδες
Coarse Dots Χοντρές κουκκίδες
@@ -2266,6 +2273,8 @@ lighting Light Φως
Neon Glow… Λάμψη νέον…
Palette Knife… Μαχαίρι παλέτας…
Neon Glow Λάμψη νέον
Paint Daubs… Πινελιές βαφής…
Paint Daubs Πινελιές βαφής
Palette Knife Μαχαίρι παλέτας
Poster Edges… Άκρες αφίσας…
Poster Edges Άκρες αφίσας
Can't render this file because it contains an unexpected character in line 2038 and column 19.
+9
View File
@@ -37,6 +37,13 @@
Channel 4 Canal 4
Cell Size Tamaño de celda
Fine Dots Puntos finos
Simple Simple
Light Rough Rugoso claro
Dark Rough Rugoso oscuro
Wide Sharp Ancho nítido
Wide Blurry Ancho borroso
Sparkle Destello
Medium Dots Puntos medios
Grainy Dots Puntos granulados
Coarse Dots Puntos gruesos
@@ -4644,6 +4651,8 @@ lighting Light Luz
Neon Glow… Resplandor de neón…
Palette Knife… Espátula…
Neon Glow Resplandor de neón
Paint Daubs… Pinceladas…
Paint Daubs Pinceladas
Palette Knife Espátula
Poster Edges… Bordes de póster…
Poster Edges Bordes de póster
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2861,6 +2861,13 @@ lighting Light Valo
Soft Light Pehmeä valo
Crosshatch Ristiviivoitus
Fine Dots Hienot pisteet
Simple Yksinkertainen
Light Rough Vaalea karkea
Dark Rough Tumma karkea
Wide Sharp Leveä terävä
Wide Blurry Leveä sumea
Sparkle Kimallus
Medium Dots Keskikokoiset pisteet
Grainy Dots Rakeiset pisteet
Coarse Dots Karkeat pisteet
@@ -4951,6 +4958,8 @@ imageTrace Outline Ääriviiva
Neon Glow… Neonhehku…
Palette Knife… Palettiveitsi…
Neon Glow Neonhehku
Paint Daubs… Maalitahrat…
Paint Daubs Maalitahrat
Palette Knife Palettiveitsi
Poster Edges… Julisteen reunat…
Poster Edges Julisteen reunat
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -38,6 +38,13 @@
Channel 4 Couche 4
Cell Size Taille de cellule
Fine Dots Points fins
Simple Simple
Light Rough Rugueux clair
Dark Rough Rugueux foncé
Wide Sharp Large net
Wide Blurry Large flou
Sparkle Scintillement
Medium Dots Points moyens
Grainy Dots Points granuleux
Coarse Dots Gros points
@@ -4654,6 +4661,8 @@ lighting Light Lumière
Neon Glow… Néon…
Palette Knife… Couteau à palette…
Neon Glow Néon
Paint Daubs… Empâtements…
Paint Daubs Empâtements
Palette Knife Couteau à palette
Poster Edges… Bords d’affiche…
Poster Edges Bords d’affiche
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -1401,6 +1401,13 @@
Find Next Következő keresése
Find Objects Objektumok keresése
Fine Dots Finom pontok
Simple Egyszerű
Light Rough Világos durva
Dark Rough Sötét durva
Wide Sharp Széles éles
Wide Blurry Széles elmosott
Sparkle Csillogás
First Első
First Baseline Első alapvonal
First commit Első commit
@@ -1587,6 +1594,8 @@ file-filter Templates Sablonok
Neon Glow… Neonfény…
Palette Knife… Palettakés…
Neon Glow Neonfény
Paint Daubs… Festékpaca…
Paint Daubs Festékpaca
Palette Knife Palettakés
Poster Edges… Poszterszélek…
Poster Edges Poszterszélek
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2688,6 +2688,13 @@ lighting Light Cahaya
Soft Light Cahaya lembut
Crosshatch Arsir silang
Fine Dots Titik halus
Simple Sederhana
Light Rough Kasar terang
Dark Rough Kasar gelap
Wide Sharp Lebar tajam
Wide Blurry Lebar buram
Sparkle Kilau
Medium Dots Titik sedang
Grainy Dots Titik berbutir
Coarse Dots Titik kasar
@@ -5183,6 +5190,8 @@ swatch Bright Violet Violet cerah
Cutout Potongan
Dry Brush Kuas kering
Neon Glow Pendar neon
Paint Daubs… Coretan cat…
Paint Daubs Coretan cat
Palette Knife Pisau palet
Poster Edges Tepi poster
Apply Data Set Terapkan set data
Can't render this file because it contains an unexpected character in line 3808 and column 19.
+9
View File
@@ -37,6 +37,13 @@
Channel 4 Canale 4
Cell Size Dimensione cella
Fine Dots Punti fini
Simple Semplice
Light Rough Ruvido chiaro
Dark Rough Ruvido scuro
Wide Sharp Ampio nitido
Wide Blurry Ampio sfocato
Sparkle Scintillio
Medium Dots Punti medi
Grainy Dots Punti granulosi
Coarse Dots Punti grossi
@@ -4686,6 +4693,8 @@ lighting Light Luce
Neon Glow… Bagliore neon…
Palette Knife… Spatola…
Neon Glow Bagliore neon
Paint Daubs… Pennellate…
Paint Daubs Pennellate
Palette Knife Spatola
Poster Edges… Bordi poster…
Poster Edges Bordi poster
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -3760,6 +3760,13 @@ theme Appearance 外観
Channel 4 チャンネル 4
Cell Size セルの大きさ
Fine Dots 細かい点
Simple シンプル
Light Rough ライトラフ
Dark Rough ダークラフ
Wide Sharp ワイドシャープ
Wide Blurry ワイドブラー
Sparkle スパークル
Medium Dots 中程度の点
Grainy Dots 粒状の点
Coarse Dots 粗い点
@@ -4725,6 +4732,8 @@ lighting Light ライト
Neon Glow… ネオングロー…
Palette Knife… パレットナイフ…
Neon Glow ネオングロー
Paint Daubs… ペイントダブ…
Paint Daubs ペイントダブ
Palette Knife パレットナイフ
Poster Edges… ポスターエッジ…
Poster Edges ポスターエッジ
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2500,6 +2500,13 @@ lighting Light სინათლე
Soft Light რბილი სინათლე
Crosshatch ჯვარედინი დაშტრიხვა
Fine Dots წვრილი წერტილები
Simple მარტივი
Light Rough ღია ხასიათიანი
Dark Rough მუქი ხასიათიანი
Wide Sharp ფართო მკვეთრი
Wide Blurry ფართო ბუნდოვანი
Sparkle ციმციმი
Medium Dots საშუალო წერტილები
Grainy Dots მარცვლოვანი წერტილები
Coarse Dots მსხვილი წერტილები
@@ -5077,6 +5084,8 @@ imageTrace Outline კონტური
Move Slice ნაჭრის გადაადგილება
Move Type on a Path ტრაექტორიაზე ტექსტის გადაადგილება
Neon Glow ნეონის ნათება
Paint Daubs… საღებავის კვეთები…
Paint Daubs საღებავის კვეთები
Palette Knife პალეტის დანა
Neon Glow… ნეონის ნათება…
Palette Knife… პალეტის დანა…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -3745,6 +3745,13 @@ theme Appearance 외관
Channel 4 채널 4
Cell Size 셀 크기
Fine Dots 고운 점
Simple 단순
Light Rough 밝은 거칠기
Dark Rough 어두운 거칠기
Wide Sharp 넓고 선명
Wide Blurry 넓고 흐림
Sparkle 반짝임
Medium Dots 중간 점
Grainy Dots 거친 입자 점
Coarse Dots 굵은 점
@@ -4649,6 +4656,8 @@ lighting Light 광원
Neon Glow… 네온 글로…
Palette Knife… 팔레트 나이프…
Neon Glow 네온 글로
Paint Daubs… 페인트 다브…
Paint Daubs 페인트 다브
Palette Knife 팔레트 나이프
Poster Edges… 포스터 가장자리…
Poster Edges 포스터 가장자리
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2702,6 +2702,13 @@ lighting Light Licht
Soft Light Zacht licht
Crosshatch Kruisarcering
Fine Dots Fijne stippen
Simple Eenvoudig
Light Rough Licht ruw
Dark Rough Donker ruw
Wide Sharp Breed scherp
Wide Blurry Breed wazig
Sparkle Fonkel
Medium Dots Middelgrote stippen
Grainy Dots Korrelige stippen
Coarse Dots Grove stippen
@@ -5194,6 +5201,8 @@ swatch Bright Violet Felviolet
Cutout Knipsel
Dry Brush Droog penseel
Neon Glow Neongloed
Paint Daubs… Verfstipjes…
Paint Daubs Verfstipjes
Palette Knife Paletmes
Poster Edges Posterranden
Apply Data Set Gegevensset toepassen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -2793,6 +2793,13 @@ lighting Light Światło
Soft Light Łagodne światło
Crosshatch Kreskowanie krzyżowe
Fine Dots Drobne kropki
Simple Prosty
Light Rough Jasny szorstki
Dark Rough Ciemny szorstki
Wide Sharp Szeroki ostry
Wide Blurry Szeroki rozmyty
Sparkle Iskra
Medium Dots Średnie kropki
Grainy Dots Ziarniste kropki
Coarse Dots Grube kropki
@@ -4889,6 +4896,8 @@ imageTrace Outline Kontur
Neon Glow… Neonowa poświata…
Palette Knife… Szpachel…
Neon Glow Neonowa poświata
Paint Daubs… Plamy farby…
Paint Daubs Plamy farby
Palette Knife Szpachel
Poster Edges… Krawędzie plakatu…
Poster Edges Krawędzie plakatu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -4046,6 +4046,8 @@ axis Both Ambos
Neon Glow… Brilho neon…
Palette Knife… Espátula…
Neon Glow Brilho neon
Paint Daubs… Manchas de tinta…
Paint Daubs Manchas de tinta
Palette Knife Espátula
Poster Edges… Bordas de pôster…
Poster Edges Bordas de pôster
@@ -4111,6 +4113,13 @@ axis Both Ambos
Channel 4 Canal 4
Cell Size Tamanho da Célula
Fine Dots Pontos Finos
Simple Simples
Light Rough Áspero claro
Dark Rough Áspero escuro
Wide Sharp Largo nítido
Wide Blurry Largo borrado
Sparkle Brilho
Medium Dots Pontos Médios
Grainy Dots Pontos Granulados
Coarse Dots Pontos Grossos
Can't render this file because it contains an unexpected character in line 6 and column 47.
+9
View File
@@ -35,6 +35,13 @@
Channel 4 Канал 4
Cell Size Размер ячейки
Fine Dots Мелкие точки
Simple Простой
Light Rough Светлая грубость
Dark Rough Тёмная грубость
Wide Sharp Широкий резкий
Wide Blurry Широкий размытый
Sparkle Блеск
Medium Dots Средние точки
Grainy Dots Зернистые точки
Coarse Dots Крупные точки
@@ -4682,6 +4689,8 @@ lighting Light Свет
Neon Glow… Неоновое свечение…
Palette Knife… Нож для палитры…
Neon Glow Неоновое свечение
Paint Daubs… Мазки кисти…
Paint Daubs Мазки кисти
Palette Knife Нож для палитры
Poster Edges… Края плаката…
Poster Edges Края плаката
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -34,6 +34,13 @@
Channel 4 Kanal 4
Cell Size Cellstorlek
Fine Dots Fina punkter
Simple Enkel
Light Rough Lätt grov
Dark Rough Mörk grov
Wide Sharp Bred skarp
Wide Blurry Bred suddig
Sparkle Glittra
Medium Dots Medelstora punkter
Grainy Dots Korniga punkter
Coarse Dots Grova punkter
@@ -4563,6 +4570,8 @@ lighting Light Ljus
Neon Glow… Neonsken…
Palette Knife… Palettkniv…
Neon Glow Neonsken
Paint Daubs… Färgklickar…
Paint Daubs Färgklickar
Palette Knife Palettkniv
Poster Edges… Affischkanter…
Poster Edges Affischkanter
Can't render this file because it contains an unexpected character in line 5 and column 25.
+9
View File
@@ -36,6 +36,13 @@
Channel 4 Канал 4
Cell Size Розмір комірки
Fine Dots Дрібні точки
Simple Простий
Light Rough Світла грубість
Dark Rough Темна грубість
Wide Sharp Широкий різкий
Wide Blurry Широкий розмитий
Sparkle Іскра
Medium Dots Середні точки
Grainy Dots Зернисті точки
Coarse Dots Великі точки
@@ -4666,6 +4673,8 @@ lighting Light Світло
Neon Glow… Неонове сяйво…
Palette Knife… Ніж палітри…
Neon Glow Неонове сяйво
Paint Daubs… Мазки фарби…
Paint Daubs Мазки фарби
Palette Knife Ніж палітри
Poster Edges… Плакатні краї…
Poster Edges Плакатні краї
Can't render this file because it contains an unexpected character in line 733 and column 40.
+9
View File
@@ -1275,6 +1275,8 @@
Neon Glow… Ánh neon…
Palette Knife… Dao palette…
Neon Glow Ánh neon
Paint Daubs… Vệt sơn…
Paint Daubs Vệt sơn
Palette Knife Dao palette
Poster Edges… Viền áp phích…
Poster Edges Viền áp phích
@@ -1299,6 +1301,13 @@
Find Next Tìm tiếp
Find Objects Tìm đối tượng
Fine Dots Chấm mịn
Simple Đơn giản
Light Rough Thô sáng
Dark Rough Thô tối
Wide Sharp Rộng sắc
Wide Blurry Rộng mờ
Sparkle Lấp lánh
First Đầu tiên
First commit Commit đầu tiên
First Page Trang đầu
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
1275
1276
1277
1278
1279
1280
1281
1282
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
+9
View File
@@ -4761,6 +4761,13 @@ axis Both 两者
Channel 4 色版 4
Cell Size 单元格大小
Fine Dots 细点
Simple 简单
Light Rough 浅色粗糙
Dark Rough 深色粗糙
Wide Sharp 宽锐
Wide Blurry 宽模糊
Sparkle 闪光
Medium Dots 中等点
Grainy Dots 颗粒点
Coarse Dots 粗点
@@ -4950,6 +4957,8 @@ lighting Light 光源
Neon Glow… 霓虹灯光…
Palette Knife… 调色刀…
Neon Glow 霓虹灯光
Paint Daubs… 绘画涂抹…
Paint Daubs 绘画涂抹
Palette Knife 调色刀
Poster Edges… 海报边缘…
Poster Edges 海报边缘
Can't render this file because it contains an unexpected character in line 2 and column 73.
+9
View File
@@ -4567,6 +4567,13 @@ axis Both 兩者
Channel 4 色版 4
Cell Size 單元大小
Fine Dots 細點
Simple 簡單
Light Rough 淺色粗糙
Dark Rough 深色粗糙
Wide Sharp 寬銳
Wide Blurry 寬模糊
Sparkle 閃光
Medium Dots 中等點
Grainy Dots 顆粒點
Coarse Dots 粗點
@@ -4756,6 +4763,8 @@ lighting Light 光源
Neon Glow… 霓虹光…
Palette Knife… 調色刀…
Neon Glow 霓虹光
Paint Daubs… 繪畫塗抹…
Paint Daubs 繪畫塗抹
Palette Knife 調色刀
Poster Edges… 海報邊緣…
Poster Edges 海報邊緣
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -4189,6 +4189,7 @@ pub fn menu_strings() -> std::collections::BTreeSet<String> {
out.extend(crate::prefs_dialog::UI_FIELDS.iter().map(|f| f.2.to_string()));
out.extend(crate::dialogs::button_labels().into_iter().map(str::to_string));
out.extend(crate::dialogs::FILM_GRAIN_FIELDS.iter().map(|(_, label, _)| label.to_string()));
out.extend(crate::dialogs::PAINT_DAUB_BRUSH_TYPE_LABELS.iter().map(|label| label.to_string()));
out.extend(crate::chrome::hint_strings().into_iter().map(str::to_string));
out.remove("");
out
+17
View File
@@ -93,6 +93,7 @@ fn effect_menu_lists_the_artistic_filters_before_blur() {
"Dry Brush…",
"Film Grain…",
"Neon Glow…",
"Paint Daubs…",
"Palette Knife…",
"Plastic Wrap…",
"Poster Edges…",
@@ -108,6 +109,22 @@ fn effect_menu_lists_the_artistic_filters_before_blur() {
assert!(at("Artistic") < at("Blur"));
}
/// Paint Daubs' Brush Type menu matches Illustrator's list and uses the effect choice labels.
#[test]
fn paint_daubs_brush_type_menu_matches_illustrator() {
use crate::dialogs::PAINT_DAUB_BRUSH_TYPE_LABELS;
use serde_json::Map;
use vectorcraft_effects::pixel::PAINT_DAUB_BRUSH_TYPES;
let catalog: Vec<&str> = PAINT_DAUB_BRUSH_TYPES.iter().map(|(label, _)| *label).collect();
assert_eq!(PAINT_DAUB_BRUSH_TYPE_LABELS.as_slice(), catalog.as_slice());
let params = Map::new();
let shown = crate::dialogs::shown_choices("artistic.paintDaubs", "brushType", &params, false).unwrap();
assert_eq!(shown.len(), PAINT_DAUB_BRUSH_TYPES.len());
for ((label, value), (english, id)) in shown.iter().zip(PAINT_DAUB_BRUSH_TYPES.iter()) {
assert_eq!((label.as_str(), value.as_str()), (*english, *id));
}
}
#[test]
fn effect_menu_lists_the_pixelate_filters_between_blur_and_sharpen() {
let app = app();
+2 -2
View File
@@ -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 | 47 | 82% | 8–14 |
| 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,7 +38,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 | 8/15 (approximate Cutout, Film Grain, Neon Glow, Plastic Wrap, Poster Edges, Smudge Stick, Sponge, Watercolor) | Colored Pencil, Dry Brush, 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 | — |
| Distort | Diffuse Glow, Glass, Ocean Ripple | 3/3 | — |