mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
G2: Effect › Sketch › Water Paper raster filter (#2955)
This commit is contained in:
@@ -253,7 +253,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 (11 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 and Stamp under Sketch) and the Effect Gallery;
|
||||
- most of the raster effects (10 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 and Water Paper under Sketch) and the Effect Gallery;
|
||||
- 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.
|
||||
|
||||
+3
-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 46/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 47/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) | 81% | 8–14 |
|
||||
| Raster effects (Effect Gallery) — [effects-parity.md](docs/effects-parity.md) | 82% | 8–14 |
|
||||
| 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,7 +123,7 @@ 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 11 remaining filters (7 Artistic, 3 Sketch, 1 more) and the Effect Gallery, 8–14 h.
|
||||
5. **Raster effects** (G2) alongside: the 10 remaining filters (7 Artistic, 2 Sketch, 1 more) and the Effect Gallery, 8–14 h.
|
||||
6. **Then:** type core and advanced type (G4), the Illustrator 2026 additions (G13), 3D (G3).
|
||||
|
||||
## Progress log
|
||||
|
||||
@@ -156,6 +156,7 @@ fn lengths_of(id: &str) -> Lengths {
|
||||
"sketch.graphicPen" => always(&["strokeLength"]),
|
||||
"sketch.halftonePattern" => always(&["size"]),
|
||||
"sketch.notePaper" => always(&["relief"]),
|
||||
"sketch.waterPaper" => always(&["fiberLength"]),
|
||||
RASTERIZE => always(&["addAround"]),
|
||||
_ => Lengths::default(),
|
||||
}
|
||||
@@ -574,6 +575,13 @@ pub fn effect_catalog() -> Vec<EffectInfo> {
|
||||
"{lightDarkBalance: 0..50 (25; the larger, the more of the object prints black), smoothness: 1..50 (5; rounds the shapes)} simplifies the object to solid black and white, as a rubber stamp would print it. Coverage is kept. Original visual approximation; chosen VectorCraft defaults.",
|
||||
json!({"lightDarkBalance": 25.0, "smoothness": 5.0}),
|
||||
),
|
||||
r(
|
||||
"sketch.waterPaper",
|
||||
"Water Paper…",
|
||||
SKETCH,
|
||||
"{fiberLength: pt 3..50 (15; scale of paper fibers and blotchy daubs), brightness: 0..100 (50), contrast: 0..100 (50)} washes the object's colours as if painted on damp fibrous paper, with soft flow and a fibrous modulation (behaviour per https://helpx.adobe.com/illustrator/using/summary-effects.html). Public helpx names Fiber Length, Brightness and Contrast but not slider ranges or dialog defaults; ranges and defaults here are unverified VectorCraft choices. Original visual approximation, not a proprietary reproduction.",
|
||||
json!({"fiberLength": 15.0, "brightness": 50.0, "contrast": 50.0}),
|
||||
),
|
||||
r(
|
||||
"stylize.glowingEdges",
|
||||
"Glowing Edges…",
|
||||
|
||||
@@ -43,7 +43,7 @@ pub use sketch::{HALFTONE_TYPES, HalftonePattern};
|
||||
pub use texture::{GRAIN_TYPES, Grain, LIGHT_DIRECTIONS, Light, TEXTURES, Texture};
|
||||
|
||||
/// The Photoshop-style effect ids (all raster effects, see [`crate::is_raster`]).
|
||||
pub const PIXEL_EFFECTS: [&str; 46] = [
|
||||
pub const PIXEL_EFFECTS: [&str; 47] = [
|
||||
"artistic.cutout",
|
||||
"artistic.filmGrain",
|
||||
"artistic.neonGlow",
|
||||
@@ -81,6 +81,7 @@ pub const PIXEL_EFFECTS: [&str; 46] = [
|
||||
"sketch.plaster",
|
||||
"sketch.reticulation",
|
||||
"sketch.stamp",
|
||||
"sketch.waterPaper",
|
||||
"stylize.glowingEdges",
|
||||
"texture.craquelure",
|
||||
"texture.grain",
|
||||
@@ -202,6 +203,10 @@ pub enum PixelFx {
|
||||
/// Sketch › Reticulation: black ink on white paper through a high-contrast film-grain screen;
|
||||
/// `density` (0..50), `foreground` and `background` (0..50) pull tones before the grain.
|
||||
Reticulation { density: f64, foreground: f64, background: f64 },
|
||||
/// Sketch › Water Paper: colours flow on damp fibrous paper; `fiber_length` (3..50) sets the
|
||||
/// fibers and daubs, `brightness` and `contrast` (0..100) adjust the wash. Ranges and defaults
|
||||
/// are unverified VectorCraft choices (helpx documents the controls only).
|
||||
WaterPaper { fiber_length: f64, brightness: f64, contrast: f64 },
|
||||
/// Stylize › Glowing Edges: bright coloured Sobel outlines on black.
|
||||
GlowingEdges { width: f64, brightness: f64, smoothness: f64 },
|
||||
/// Pixelate › Color Halftone: each colour channel screened at its angle (`angles`° of channels
|
||||
@@ -438,6 +443,11 @@ pub(crate) fn parse(id: &str, p: &Value) -> Option<PixelFx> {
|
||||
foreground: num(p, "foregroundLevel", 6.0).clamp(0.0, 50.0),
|
||||
background: num(p, "backgroundLevel", 6.0).clamp(0.0, 50.0),
|
||||
},
|
||||
"sketch.waterPaper" => PixelFx::WaterPaper {
|
||||
fiber_length: num(p, "fiberLength", 15.0).clamp(3.0, 50.0),
|
||||
brightness: num(p, "brightness", 50.0).clamp(0.0, 100.0),
|
||||
contrast: num(p, "contrast", 50.0).clamp(0.0, 100.0),
|
||||
},
|
||||
"stylize.glowingEdges" => PixelFx::GlowingEdges {
|
||||
width: num(p, "edgeWidth", 2.0).clamp(1.0, 14.0),
|
||||
brightness: num(p, "edgeBrightness", 6.0).clamp(0.0, 20.0),
|
||||
@@ -524,6 +534,7 @@ impl PixelFx {
|
||||
| PixelFx::Plaster { .. }
|
||||
| PixelFx::Reticulation { .. } => 0.0,
|
||||
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),
|
||||
// These three keep the object's coverage.
|
||||
PixelFx::SmudgeStick { .. } | PixelFx::Sponge { .. } | PixelFx::Watercolor { .. } => 0.0,
|
||||
@@ -590,6 +601,7 @@ impl PixelFx {
|
||||
| PixelFx::NotePaper { .. }
|
||||
| PixelFx::Reticulation { .. } => Some(0.0),
|
||||
PixelFx::Plaster { smoothness, .. } => Some(sketch::plaster_reach(smoothness)),
|
||||
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)),
|
||||
// Cutout's palette comes from the whole object.
|
||||
PixelFx::Cutout { .. } => None,
|
||||
// The softened tones around the pixel.
|
||||
@@ -659,6 +671,9 @@ impl PixelFx {
|
||||
PixelFx::Stamp { balance, smoothness } => sketch_ink::stamp(px, w, h, space, balance, smoothness),
|
||||
PixelFx::Plaster { image_balance, smoothness, light } => sketch::plaster(px, w, h, space, image_balance, smoothness, light),
|
||||
PixelFx::Reticulation { density, foreground, background } => sketch::reticulation(px, w, h, space, density, foreground, background),
|
||||
PixelFx::WaterPaper { fiber_length, brightness, contrast } => {
|
||||
sketch::water_paper(px, w, h, space, fiber_length, brightness, contrast)
|
||||
}
|
||||
PixelFx::GlowingEdges { width, brightness, smoothness } => edges::glow(px, w, h, to_px(width), brightness, to_px(smoothness)),
|
||||
PixelFx::ColorHalftone { max_radius, angles } => pixelate::color_halftone(px, w, h, space, max_radius, angles),
|
||||
PixelFx::Crystallize { cell } => pixelate::crystallize(px, w, h, space, cell),
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
//! Effect › Sketch (Chalk & Charcoal, Chrome, Halftone Pattern, Note Paper, Plaster and Reticulation; Graphic Pen lives in
|
||||
//! Effect › Sketch (Chalk & Charcoal, Chrome, Halftone Pattern, Note Paper, Plaster, Reticulation 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) and the public Photoshop Elements Artistic filters guide. Visual
|
||||
//! black and white; Water Paper flows colours on damp fibrous paper) and the public Photoshop Elements Artistic filters guide. Visual
|
||||
//! approximations, not proprietary reproductions.
|
||||
|
||||
use std::f64::consts::{FRAC_1_SQRT_2, TAU};
|
||||
|
||||
use vectorcraft_geom::Vec2;
|
||||
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};
|
||||
@@ -15,6 +16,7 @@ use super::{PixelSpace, blur_plane, pick};
|
||||
|
||||
const SALT_CHALK: u64 = 216;
|
||||
const SALT_CHROME: u64 = 0xC40_4D45;
|
||||
const SALT_WATER: u64 = 208;
|
||||
const EDGE_SOFT: f64 = 0.8;
|
||||
const TONE_SOFT: f64 = 1.0;
|
||||
/// Light from the top left (document axes, y down), as on polished relief surfaces.
|
||||
@@ -357,3 +359,74 @@ pub(super) fn reticulation(px: &mut [[u8; 4]], w: usize, h: usize, space: &Pixel
|
||||
*p = premultiply([(1.0 - ink) as f32; 3], f32::from(p[3]) / 255.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// How far Water Paper's blotchy displacement can shift content (document units).
|
||||
pub(super) fn water_paper_shift(fiber_length: f64) -> f64 {
|
||||
0.12 * fiber_length.clamp(3.0, 50.0)
|
||||
}
|
||||
|
||||
/// Water Paper: colours flow on damp fibrous paper. `fiber_length` (3..50) sets the scale of the
|
||||
/// fibers and daubs; `brightness` and `contrast` (0..100) adjust the washed result. Ranges and
|
||||
/// defaults are documented in [`crate::effect_catalog`] (unverified; helpx lists the controls only).
|
||||
pub(super) fn water_paper(px: &mut [[u8; 4]], w: usize, h: usize, space: &PixelSpace, fiber_length: f64, brightness: f64, contrast: f64) {
|
||||
if !(fiber_length.is_finite() && brightness.is_finite() && contrast.is_finite()) {
|
||||
return;
|
||||
}
|
||||
let Some(place) = Place::new(space, w, h) else { return };
|
||||
let fiber = fiber_length.clamp(3.0, 50.0);
|
||||
let bright = (brightness / 100.0).clamp(0.0, 1.0);
|
||||
let cont = (contrast / 100.0).clamp(0.0, 1.0);
|
||||
let shift = water_paper_shift(fiber);
|
||||
let wave = fiber * 0.4;
|
||||
displace(px, w, h, &place, shift, |q| {
|
||||
let a = 0.65 * smooth_noise(SALT_WATER, q, wave) + 0.35 * smooth_noise(SALT_WATER + 3, q, wave * 1.7);
|
||||
let b = 0.65 * smooth_noise(SALT_WATER + 1, q, wave * 1.1) + 0.35 * smooth_noise(SALT_WATER + 4, q, wave * 0.85);
|
||||
Vec2::new(a, b) * shift
|
||||
});
|
||||
let flow = (0.06 * fiber).max(0.35) / place.px.max(1e-9);
|
||||
let mut planes: [Vec<f32>; 3] = std::array::from_fn(|ch| px.iter().map(|p| straight(*p)[ch] * f32::from(p[3]) / 255.0).collect());
|
||||
for plane in &mut planes {
|
||||
blur_plane(plane, w, h, flow);
|
||||
}
|
||||
for (i, p) in px.iter_mut().enumerate() {
|
||||
if p[3] == 0 {
|
||||
continue;
|
||||
}
|
||||
let a = f32::from(p[3]) / 255.0;
|
||||
if a <= 0.0 {
|
||||
continue;
|
||||
}
|
||||
let rgb = {
|
||||
let mut rgb = [0.0f32; 3];
|
||||
let mut ok = true;
|
||||
for ch in 0..3 {
|
||||
let Some(v) = planes[ch].get(i) else {
|
||||
ok = false;
|
||||
break;
|
||||
};
|
||||
rgb[ch] = (*v / a).clamp(0.0, 1.0);
|
||||
}
|
||||
if !ok {
|
||||
continue;
|
||||
}
|
||||
rgb
|
||||
};
|
||||
*p = premultiply(rgb, a);
|
||||
}
|
||||
let lift = (bright - 0.5) * 0.35;
|
||||
let gain = 0.35 + 0.65 * cont;
|
||||
place.each(px, |x, y, p| {
|
||||
if p[3] == 0 {
|
||||
return;
|
||||
}
|
||||
let q = place.at(x, y);
|
||||
let along = smooth_noise(SALT_WATER + 5, q, fiber * 0.25);
|
||||
let across = smooth_noise(SALT_WATER + 6, Point::new(q.y, q.x), fiber * 0.22);
|
||||
let fiber_tex = (0.5 * (along + across) + 0.5).clamp(0.0, 1.0);
|
||||
let paper = (0.82 + 0.18 * fiber_tex) as f32;
|
||||
let mut rgb = straight(*p).map(|v| ((v + lift as f32 - 0.5) * gain as f32 + 0.5).clamp(0.0, 1.0));
|
||||
rgb = rgb.map(|v| (v * paper).clamp(0.0, 1.0));
|
||||
*p = premultiply(rgb, f32::from(p[3]) / 255.0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2046,6 +2046,13 @@ fn halftone(p: serde_json::Value, src: &[u8], w: usize, h: usize, s: &PixelSpace
|
||||
out
|
||||
}
|
||||
|
||||
/// Water Paper of `p` over `w` × `h` pixels of `src`, laid out by `s`.
|
||||
fn water_paper(p: serde_json::Value, src: &[u8], w: usize, h: usize, s: &PixelSpace) -> Vec<u8> {
|
||||
let mut out = src.to_vec();
|
||||
fx("sketch.waterPaper", p).apply(&mut out, w, h, s);
|
||||
out
|
||||
}
|
||||
|
||||
/// The smallest period of `values` (their length when they don't repeat).
|
||||
fn period(values: &[u8]) -> usize {
|
||||
(1..values.len()).find(|p| values.iter().zip(&values[*p..]).all(|(a, b)| a == b)).unwrap_or(values.len())
|
||||
@@ -2144,6 +2151,41 @@ fn note_paper_embosses_a_gradient_and_grain_changes_pixels() {
|
||||
assert_ne!(flat, grainy, "graininess adds fibre");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn water_paper_params_take_defaults_and_stay_in_range() {
|
||||
assert_eq!(
|
||||
fx("sketch.waterPaper", json!({})),
|
||||
PixelFx::WaterPaper { fiber_length: 15.0, brightness: 50.0, contrast: 50.0 }
|
||||
);
|
||||
assert_eq!(
|
||||
fx("sketch.waterPaper", json!({"fiberLength": 1, "brightness": -5, "contrast": 200})),
|
||||
PixelFx::WaterPaper { fiber_length: 3.0, brightness: 0.0, contrast: 100.0 }
|
||||
);
|
||||
let f = fx("sketch.waterPaper", json!({"fiberLength": 40}));
|
||||
assert!(f.outset(Rect::new(0.0, 0.0, 100.0, 50.0)) > 0.0);
|
||||
assert!(f.reach().unwrap_or(0.0) > 0.0);
|
||||
let doc = crate::effect_info("sketch.waterPaper").unwrap().params;
|
||||
assert!(
|
||||
doc.contains("helpx.adobe.com/illustrator/using/summary-effects.html") && doc.contains("unverified"),
|
||||
"{doc}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn water_paper_softens_and_textures_a_flat_fill_without_losing_coverage() {
|
||||
let (w, h) = (64, 64);
|
||||
let src = image(w, h, |_, _| [200, 80, 40, 255]);
|
||||
let out = water_paper(json!({"fiberLength": 20, "brightness": 50, "contrast": 40}), &src, w, h, &space(w, h));
|
||||
assert!(out.chunks_exact(4).filter(|p| p[3] > 200).count() > w * h / 2, "most of the fill stays visible");
|
||||
assert_ne!(out, src, "the wash changes pixels");
|
||||
let spread = |d: &[u8]| {
|
||||
let reds: Vec<u8> = d.chunks_exact(4).map(|p| p[0]).collect();
|
||||
let (min, max) = (reds.iter().min().unwrap(), reds.iter().max().unwrap());
|
||||
max - min
|
||||
};
|
||||
assert!(spread(&out) > spread(&src) / 2, "fibers add tonal variation");
|
||||
}
|
||||
|
||||
/// Line's rows repeat every Size points: Size pixels at 72 ppi, twice as many at 144 ppi.
|
||||
#[test]
|
||||
fn halftone_line_period_is_the_size_at_any_resolution() {
|
||||
|
||||
@@ -52,7 +52,7 @@ const PIXELATE: [(&str, &str); 4] =
|
||||
[("pixelate.colorHalftone", "{}"), ("pixelate.crystallize", "{}"), ("pixelate.mezzotint", "{}"), ("pixelate.pointillize", "{}")];
|
||||
|
||||
/// Effect › Sketch, at their defaults.
|
||||
const SKETCH: [(&str, &str); 11] = [
|
||||
const SKETCH: [(&str, &str); 12] = [
|
||||
("sketch.basRelief", "{}"),
|
||||
("sketch.chalkCharcoal", "{}"),
|
||||
("sketch.charcoal", "{}"),
|
||||
@@ -64,6 +64,7 @@ const SKETCH: [(&str, &str); 11] = [
|
||||
("sketch.plaster", "{}"),
|
||||
("sketch.reticulation", "{}"),
|
||||
("sketch.stamp", "{}"),
|
||||
("sketch.waterPaper", "{}"),
|
||||
];
|
||||
|
||||
/// Effect › Texture, at their defaults.
|
||||
|
||||
@@ -5233,3 +5233,5 @@ theme Appearance Външен вид
|
||||
Plaster Гипс
|
||||
Note Paper… Хартия за писма…
|
||||
Note Paper Хартия за писма
|
||||
Water Paper… Мокра хартия…
|
||||
Water Paper Мокра хартия
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5273,3 +5273,5 @@ mark-style Japanese Japonské
|
||||
Plaster Sádra
|
||||
Note Paper… Dopisní papír…
|
||||
Note Paper Dopisní papír
|
||||
Water Paper… Mokrý papír…
|
||||
Water Paper Mokrý papír
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5251,3 +5251,5 @@ swatch Bright Violet Kraftig violet
|
||||
Plaster Gips
|
||||
Note Paper… Notatpapir…
|
||||
Note Paper Notatpapir
|
||||
Water Paper… Vådt papir…
|
||||
Water Paper Vådt papir
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4854,3 +4854,5 @@ effect Soft Weich
|
||||
Plaster Gipsabdruck
|
||||
Note Paper… Prägepapier…
|
||||
Note Paper Prägepapier
|
||||
Water Paper… Feuchtes Papier…
|
||||
Water Paper Feuchtes Papier
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5225,3 +5225,5 @@ effect Points Σημεία
|
||||
Plaster Γύψος
|
||||
Note Paper… Χαρτί σημειώσεων…
|
||||
Note Paper Χαρτί σημειώσεων
|
||||
Water Paper… Βρεγμένο χαρτί…
|
||||
Water Paper Βρεγμένο χαρτί
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2017 and column 19.
|
@@ -5215,3 +5215,5 @@ mark-style Japanese Japonesas
|
||||
Plaster Yeso
|
||||
Note Paper… Papel con relieve…
|
||||
Note Paper Papel con relieve
|
||||
Water Paper… Papel mojado…
|
||||
Water Paper Papel mojado
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5304,3 +5304,5 @@ swatch Bright Violet Kirkas violetti
|
||||
Plaster Kipsi
|
||||
Note Paper… Kirjepaperi…
|
||||
Note Paper Kirjepaperi
|
||||
Water Paper… Märkä paperi…
|
||||
Water Paper Märkä paperi
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5272,3 +5272,5 @@ theme Appearance Apparence
|
||||
Plaster Plâtre
|
||||
Note Paper… Papier gaufré…
|
||||
Note Paper Papier gaufré
|
||||
Water Paper… Papier humide…
|
||||
Water Paper Papier humide
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5259,3 +5259,5 @@ imageTrace Outline Körvonal
|
||||
Plaster Gipsz
|
||||
Note Paper… Jegyzetpapír…
|
||||
Note Paper Jegyzetpapír
|
||||
Water Paper… Nedves papír…
|
||||
Water Paper Nedves papír
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5251,3 +5251,5 @@ swatch Bright Violet Violet cerah
|
||||
Plaster Plester
|
||||
Note Paper… Kertas Catatan…
|
||||
Note Paper Kertas Catatan
|
||||
Water Paper… Kertas Basah…
|
||||
Water Paper Kertas Basah
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3774 and column 19.
|
@@ -4887,3 +4887,5 @@ lighting Light Luce
|
||||
Plaster Gesso
|
||||
Note Paper… Carta da lettere…
|
||||
Note Paper Carta da lettere
|
||||
Water Paper… Carta bagnata…
|
||||
Water Paper Carta bagnata
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4927,3 +4927,5 @@ lighting Light ライト
|
||||
Plaster 石膏
|
||||
Note Paper… ノート用紙…
|
||||
Note Paper ノート用紙
|
||||
Water Paper… ぬれた紙…
|
||||
Water Paper ぬれた紙
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5180,3 +5180,5 @@ imageTrace Outline კონტური
|
||||
Plaster თაბაშირი
|
||||
Note Paper… ჩანაწერების ქაღალდი…
|
||||
Note Paper ჩანაწერების ქაღალდი
|
||||
Water Paper… სველი ქაღალდი…
|
||||
Water Paper სველი ქაღალდი
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4850,3 +4850,5 @@ lighting Light 광원
|
||||
Plaster 석고
|
||||
Note Paper… 메모지…
|
||||
Note Paper 메모지
|
||||
Water Paper… 물 종이…
|
||||
Water Paper 물 종이
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5293,3 +5293,5 @@ swatch Bright Violet Felviolet
|
||||
Plaster Gips
|
||||
Note Paper… Notitiepapier…
|
||||
Note Paper Notitiepapier
|
||||
Water Paper… Nat papier…
|
||||
Water Paper Nat papier
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5125,3 +5125,5 @@ mark-style Japanese Japońskie
|
||||
Plaster Gips
|
||||
Note Paper… Papier listowy…
|
||||
Note Paper Papier listowy
|
||||
Water Paper… Mokry papier…
|
||||
Water Paper Mokry papier
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5190,3 +5190,5 @@ mark-style Japanese Japonesas
|
||||
Plaster Gesso
|
||||
Note Paper… Papel de carta…
|
||||
Note Paper Papel de carta
|
||||
Water Paper… Papel molhado…
|
||||
Water Paper Papel molhado
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4883,3 +4883,5 @@ lighting Light Свет
|
||||
Plaster Гипс
|
||||
Note Paper… Почтовая бумага…
|
||||
Note Paper Почтовая бумага
|
||||
Water Paper… Мокрая бумага…
|
||||
Water Paper Мокрая бумага
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5229,3 +5229,5 @@ theme Appearance Utseende
|
||||
Plaster Gips
|
||||
Note Paper… Anteckningspapper…
|
||||
Note Paper Anteckningspapper
|
||||
Water Paper… Vått papper…
|
||||
Water Paper Vått papper
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4867,3 +4867,5 @@ lighting Light Світло
|
||||
Plaster Гіпс
|
||||
Note Paper… Поштовий папір…
|
||||
Note Paper Поштовий папір
|
||||
Water Paper… Мокрий папір…
|
||||
Water Paper Мокрий папір
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 725 and column 40.
|
@@ -4867,3 +4867,5 @@ theme Appearance Giao diện
|
||||
Plaster Thạch cao
|
||||
Note Paper… Giấy ghi chú…
|
||||
Note Paper Giấy ghi chú
|
||||
Water Paper… Giấy ướt…
|
||||
Water Paper Giấy ướt
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3964 and column 10.
|
@@ -5110,3 +5110,5 @@ lighting Light 光源
|
||||
Plaster 塑料效果
|
||||
Note Paper… 便条纸…
|
||||
Note Paper 便条纸
|
||||
Water Paper… 水彩画纸…
|
||||
Water Paper 水彩画纸
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4905,3 +4905,5 @@ lighting Light 光源
|
||||
Plaster 塑膠效果
|
||||
Note Paper… 便條紙…
|
||||
Note Paper 便條紙
|
||||
Water Paper… 水彩畫紙…
|
||||
Water Paper 水彩畫紙
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -191,7 +191,8 @@ fn effect_menu_lists_the_sketch_filters_between_sharpen_and_stylize() {
|
||||
"Photocopy…",
|
||||
"Plaster…",
|
||||
"Reticulation…",
|
||||
"Stamp…"
|
||||
"Stamp…",
|
||||
"Water Paper…"
|
||||
]
|
||||
);
|
||||
assert!(sketch.iter().all(|e| e.command.as_deref() == Some("effect.dialog")));
|
||||
@@ -206,12 +207,13 @@ fn effect_menu_lists_the_sketch_filters_between_sharpen_and_stylize() {
|
||||
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.waterPaper"}));
|
||||
let at = |label: &str| entries.iter().position(|e| e.path[0] == "Effect" && e.label == label).unwrap();
|
||||
assert!(at("Unsharp Mask…") < at("Chalk & Charcoal…") && at("Chalk & Charcoal…") < at("Chrome…"));
|
||||
assert!(at("Chrome…") < 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("Glowing Edges…"));
|
||||
assert!(at("Reticulation…") < at("Water Paper…") && at("Water Paper…") < at("Glowing Edges…"));
|
||||
}
|
||||
|
||||
/// Effect › Stylize under Raster Effects, between Sharpen and Texture: Glowing Edges opens its
|
||||
|
||||
@@ -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 | 46 | 81% | 8–14 |
|
||||
| Photoshop effects (raster, Effect Gallery) | 57 | 47 | 82% | 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 | — | — |
|
||||
|
||||
@@ -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 | 11/14 (approximate Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp; Chalk & Charcoal, Graphic Pen and Note Paper defaults unverified) | Conté Crayon, Torn Edges, Water Paper |
|
||||
| Sketch | Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Conté Crayon, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Torn Edges, Water Paper | 12/14 (approximate Bas Relief, Chalk & Charcoal, Charcoal, Chrome, Graphic Pen, Halftone Pattern, Note Paper, Photocopy, Plaster, Reticulation, Stamp, Water Paper; Chalk & Charcoal, Graphic Pen, Note Paper and Water Paper defaults unverified) | Conté Crayon, Torn Edges |
|
||||
| Stylize | Glowing Edges | 1/1 | — |
|
||||
| Texture | Craquelure, Grain, Mosaic Tiles, Patchwork, Stained Glass, Texturizer | 6/6 | Texturizer's Load Texture |
|
||||
| Video | De-Interlace, NTSC Colors | 2/2 | — |
|
||||
@@ -178,6 +178,7 @@ angular cut caps, exact visibility, 3D Classic, Turntable, 3D export) is 25–45
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 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. |
|
||||
| 2026-10-19 | minor | Sketch › Chalk & Charcoal, Graphic Pen and Reticulation and Artistic › Plastic Wrap landed (#2972, #2967, #2976, #3034): 36/57 Photoshop effects (estimated; defaults unverified) |
|
||||
| 2026-10-16 | minor | Zig Zag with Smooth points draws a continuous wave: every peak and valley is a smooth point with handles along the path, a third of the way to the next ridge, so each span follows a half cosine through the path instead of a straight diagonal with rounded tips, also at the ends of open paths and for ridges much taller than they are apart (#2343); score unchanged (estimated) |
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ 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
|
||||
|
||||
- **Missing:** 11 of 57 filters (7 Artistic, 3 Sketch and 1 more), the Effect Gallery dialog, Load
|
||||
- **Missing:** 10 of 57 filters (7 Artistic, 2 Sketch and 1 more), the Effect Gallery dialog, Load
|
||||
Texture for Texturizer. 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:
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ Checked 2026-10-10 from the code, tests and open issues; no workflow fails, so V
|
||||
| M6 | Path operations (Pathfinder, Shape Builder, offset…) | ✅ mostly done (single-result Pathfinder names and SVG IDs retained (#1293); Divide open-cutting-path geometry, appearance and history verified (#1307; existing segment cap remains); Simplify preview/counts and rewritten-path component selection verified (#1272; auto/slider/advanced UI remains open); Compound appearance and member fill-rule edits verified (#1197); Boolean precision on almost-horizontal edges fixed and the property tests made deterministic; Shape Builder gap detection, large-offset bug open) | 3–6 |
|
||||
| M7 | Type (point/area/path, editing, styles, OpenType, threading, glyphs) | 🟡 Fullwidth `!` / `?` keep an upright fallback in vertical type; Document-point character controls after object/group scaling (#1034; optional font-size preservation remains separate), Character/Paragraph Styles (explicit Auto-leading resets and local leading overrides), per-paragraph paragraph attributes, mixed paragraph alignment indication (headless regressions, full integration CI and visual review pass), Area Type Options (with Width/Height, Auto Size and Shrink Text to Fit; overflow reported to agents and vertical Align), type areas resized by their handles and reshaped with Direct Selection, threaded text, Fit Headline, Glyphs, OpenType panel, Find Font, installed system fonts in every font menu (fonts registered with Windows outside its font folders, the XDG and Flatpak host font folders on Linux, and fonts installed while the app runs, listed when it comes back to the front; searchable; the Character and Properties menus show each family's sample of the selected text, preview it live under the pointer or ↑/↓, filter by script and kind, list a family's styles, and star favourites; the Glyphs panel and Find Font's Replace With use the same menu without the live preview) and found by name on open/import (full-name aliases and Missing Fonts searches verified, #1258; Windows font-service QA pending), variable fonts' named instances as styles, CJK names in the UI, input methods (marked text in place, candidate window at the caret; Japanese IME), Text Wrap (offset, invert, both sides of an object; follows edits), Type on a Path effects and Options with draggable start/centre/end brackets (slide, flip), tab stops + Tabs panel (Above Text floats it over the selected text, its ruler at the canvas zoom so stops line up with the columns, #729), inline symbols in text (beyond parity), Hebrew/Arabic bidirectional text, Paragraph Direction, Every-line/Single-line Composer per object (ragged text too) done; tab leaders, spell check, vertical type pending | 45–60 |
|
||||
| M8 | Transform & distort (Puppet Warp, Liquify tools, Envelopes, Blends, Perspective Grid) | ✅ done (M8.1–M8.20 on 2026-10-06, fidelity pass): Liquify Tool Options with one shared brush, pen pressure, hold-to-apply, a safe scope and incremental strokes; tool options that last; Puppet Warp rotation, multi-select, Control bar and a rest-shape session that follows Undo; Width tool on compound paths; Envelope dialogs with preview, Reset with Warp/Mesh, full Envelope Options, type/images/symbols/appearance/gradients/patterns distorted on canvas and in every export, warps that keep their frame, Edit Contents, mesh handles and Control bar; Blend Options, anchor-targeted Blend tool, editable spine, keys picked on the canvas, faithful interpolation and knockout; Anchor Point spine conversion/handle editing and selection priority (#2544), with #2425 Shift reshape preserved; Perspective Grid with Define Grid, presets, lock/snap/rulers, widgets, the 1–4 plane switch, movable planes, Perspective Selection scale/copy/perpendicular/Transform Again, and type and symbols truly projected with Edit Text. Left: Anti-Alias and Preserve Shape output, warp-envelope point editing, brush interpolation in blends, Free Transform/Scale/Reflect along a rotated box | 2–4 |
|
||||
| M9 | Live effects (+ 3D & Materials) | 🟡 2D effects done incl. Effect → Pathfinder, Color Adjustments and Document Raster Effects Settings; PDF export warns when the pixel cap lowers raster-effect resolution; Artistic › Cutout, Film Grain, Neon Glow, Poster Edges, Smudge Stick, Sponge and Watercolor and Sketch › Halftone Pattern, Bas Relief, Charcoal, Photocopy and Stamp done (46/57 Photoshop filters); Revolve with automatic smooth vector shading, default-on circular caps and continuous rims, Extrude & Bevel, Inflate and Rotate with one to ten colored directional lights; SVG Filters, remaining raster effects and 3D materials and shadows pending | 81–130 |
|
||||
| M9 | Live effects (+ 3D & Materials) | 🟡 2D effects done incl. Effect → Pathfinder, Color Adjustments and Document Raster Effects Settings; PDF export warns when the pixel cap lowers raster-effect resolution; Artistic › Cutout, Film Grain, Neon Glow, Poster Edges, Smudge Stick, Sponge and Watercolor and Sketch › Halftone Pattern, Bas Relief, Charcoal, Photocopy and Stamp done (47/57 Photoshop filters); Revolve with automatic smooth vector shading, default-on circular caps and continuous rims, Extrude & Bevel, Inflate and Rotate with one to ten colored directional lights; SVG Filters, remaining raster effects and 3D materials and shadows pending | 81–130 |
|
||||
| M10 | Brushes, symbols, patterns, Repeat | 🟡 pattern swatches (5 tile types, Pattern Options, editing mode, SVG `<pattern>`/PDF export) and live Repeat (radial/grid/mirror) done; interactive selected mirror axis implemented (focused and native checks passed; full CI blocked by an unrelated text test); brushes/symbols in progress | 23–37 |
|
||||
| M11 | Artboards & views (selected-set deletion shared by Artboards menu, trash and Properties, retaining artboard 1 when all are selected; Artboard deletion keys keep the first of an all-selected set and protect artwork; history prunes invalid indices while preserving valid multiselection (history tests and full workspace CI pass); click-to-fit objects with the Artboard tool (#1227), artboard escape routing and document setup modal handoff done; artboard panel/tool with Move Artwork for X/Y fields and Artboard Options, Trim View, middle-button pan, print tiling and the status bar's artboard navigator with synchronized Artboard tool selection done; multiple windows, presentation polish) (cached canvas reprojection preserves scale during resize, rotation and DPI changes; regression-tested and contributor-confirmed 2026-10-19; estimates unchanged) (cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission; regression-tested; estimates unchanged) | 🟡 | 15–25 |
|
||||
| M12 | Advanced color & art (CMYK/ICC, separations, Gradient Mesh, Live Paint, Image Trace, Graphs) | 🟡 Gradient Mesh, Live Paint, Image Trace (Create Strokes: exact crop EDT, Guo–Hall thinning and maximal-disc graph simplification; 15 presets, the 14 documented ones each with an enhanced version; Ignore Color, Shapes, Auto Grouping and Gradients options; measured in `image-trace-quality.md`; the Flat Logo mode places edges to a fraction of a pixel, restores sharp corners, snaps lines and circles, and refuses gradients), Recolor Artwork, colour management (ICC, soft proofing, separations preview), Graphs (all 9 tools, Graph Data/Type, group-selected series colours persist through regenerate/save/open) done; Graph Design and Marker designs, Transpose and Switch x/y, `|` label line breaks, the pie options, drop shadows, the legend across the top, overlapping widths, First Row/Column in Front, filled lines, kept label formatting and the Graph Data worksheet done; graph Column designs pending | 6–10 |
|
||||
|
||||
@@ -12,7 +12,7 @@ the work list made from it. Deep areas have their own checklists: [UI and intera
|
||||
| Number | Value | Kind |
|
||||
|---|---|---|
|
||||
| 2026-10-15 | minor | Image Trace retains nonzero positioned boundaries when a fixed-end returning piece has fewer than two fitted cubics. Source-generated tests check survival, winding, shared-edge reversal and Noise controls; see `image-trace-quality.md`. Scores and hours unchanged. |
|
||||
| **Feature breadth** (does each Illustrator menu item, tool, effect and format exist?) | **~88%** | measured in part: menu tree 353 of 375 items wired (94.1%), tools 89 of 92 (97%), vector effects 44 of 50 (88%), Photoshop-style effects 46 of 57 (81%), 3D 4 of 4 (initial: Extrude & Bevel, Revolve, Inflate, Rotate); blended by the area weights below |
|
||||
| **Feature breadth** (does each Illustrator menu item, tool, effect and format exist?) | **~88%** | measured in part: menu tree 353 of 375 items wired (94.1%), tools 89 of 92 (97%), vector effects 44 of 50 (88%), Photoshop-style effects 47 of 57 (82%), 3D 4 of 4 (initial: Extrude & Bevel, Revolve, Inflate, Rotate); blended by the area weights below |
|
||||
| **Feature depth** (each area scored by behaviour, weighted) | **~75%** | estimated, area table below |
|
||||
| **Ready for real work, mainstream illustrator** | **~65%** (60–70%) | estimated, see [Ready for real work](#ready-for-real-work) |
|
||||
| **Ready for real work, full Illustrator** (decides the stage) | **~62%** (57–67%) | estimated: additive weighted sum over the dimensions, see [Ready for real work](#ready-for-real-work) |
|
||||
@@ -75,7 +75,7 @@ dominate; 3D, graphs and automation are specialist). They sum to 105. Feature de
|
||||
| Strokes, brushes, width profiles | 5 | 88% | Shift-double-click adjoining adjustment is implemented; remaining: Art brush Overlap, Pattern brush auto corners, brush libraries, pen pressure on macOS, tilt/bearing/rotation | 8–15 | estimated; width-point creation and adjoining adjustment regression-tested; dialog layout reviewed; evidence below; finite-arithmetic follow-up regressions and full CI passed (evidence below) |
|
||||
| Appearance, transparency, graphic styles, masks | 5 | 97% | raster effect reach in preview bounds | 1–2 | estimated |
|
||||
| Live vector effects | 5 | 85% | Outline Object, Pathfinder Hard Mix/Soft Mix/Trap, SVG Filters, the Transform effect's missing options (#885) | 6–10 | measured count 46/50, depth estimated; Warp Options controls verified by focused checks and original-image review |
|
||||
| Raster effects (Effect Gallery) | 4 | 49% | 11 Photoshop-style filters (7 Artistic, 3 Sketch, 1 more), the Effect Gallery dialog, Load Texture | 8–14 | measured count 46/57; texture redraw distances optimized (#1257), pixels verified; depth estimated |
|
||||
| Raster effects (Effect Gallery) | 4 | 49% | 10 Photoshop-style filters (7 Artistic, 2 Sketch, 1 more), the Effect Gallery dialog, Load Texture | 8–14 | measured count 47/57; texture redraw distances optimized (#1257), pixels verified; depth estimated |
|
||||
| 3D and Materials (and Turntable) | 4 | ~25% | live Revolve with automatic smooth vector shading and default-on continuous circular caps, Extrude & Bevel (twist, taper, caps, five bevel shapes), Inflate and Rotate with Position presets (colored Inflate uses smooth membrane lighting; white-light Inflate retains its existing shading; Extrude & Bevel and Rotate retain planar shading; one to ten colored lights, shared neutral ambient, painter visibility); materials, light presets, shadows, ray tracing, 3D Classic, Turntable views, 3D export | 30–55 | estimated (Extrude & Bevel, Inflate and Rotate added 2026-10-12) |
|
||||
| Type core | 9 | 80% | Auto-leading style resets are implemented; remaining: hyphenation and justification options, Optical Margin Alignment, Middle Eastern features beyond bidi layout, optional group font-size preservation; transformed character controls fixed (#1034), see [type-parity.md](type-parity.md) | 14–19 | estimated; full-name font matches regression-tested (#1258); mixed paragraph alignment indication implemented; headless regressions, full integration CI and visual review pass; localized legacy family-name fallback with loaded/catalog regressions (#2208) |
|
||||
| Type advanced (CJK, spelling, Touch Type, Retype) | 4 | 50% | CJK vertical composition (ruby, mojikumi), variable font axes, tab leaders, spell check, Touch Type, Retype | 20–28 | estimated; upright fallback for fullwidth `!` / `?` regression-tested; score and hours unchanged |
|
||||
|
||||
Reference in New Issue
Block a user