Merge pull request #5866 from dotCooCoo/fix/char-strokes-scale-reuse

Rebuild fitted text geometry after scaling
This commit is contained in:
BFlat
2026-11-06 10:37:39 +08:00
committed by GitHub
3 changed files with 31 additions and 7 deletions
+5 -2
View File
@@ -164,8 +164,11 @@ impl Renderer {
.texts
.get_if(&previous, self.stamp, |(node, _)| {
let NodeKind::Text(old) = &node.kind else { return false };
// Layout and character stroke outlines are in text space. Only the transform
// changed when the remaining text attributes still compare equal.
// Shrink Text to Fit searches document-point sizes, so a scale change can
// alter layout. Translation leaves the glyphs in text space unchanged.
if old.xf.as_coeffs()[..4] != t.xf.as_coeffs()[..4] {
return false;
}
let mut comparable = (**old).clone();
comparable.xf = t.xf;
comparable == *t
+24 -3
View File
@@ -2,9 +2,9 @@
//! take every stroke option, as path strokes do.
use vectorcraft_color::{Color, Paint};
use vectorcraft_doc::text::{CharStyle, TextObject};
use vectorcraft_doc::{AppearanceItem, Dash, LineJoin, Node, NodeKind};
use vectorcraft_geom::Point;
use vectorcraft_doc::text::{CharStyle, TextKind, TextObject};
use vectorcraft_doc::{AppearanceItem, AreaFit, Dash, LineJoin, Node, NodeKind};
use vectorcraft_geom::{PathData, Point};
use crate::tests_fontchange::fonts_steady;
use crate::*;
@@ -186,6 +186,27 @@ fn moving_type_reuses_character_strokes_without_changing_pixels() {
assert_eq!(r.texts.len(), 1, "and not also under the old one");
}
#[test]
fn scaling_fitted_area_type_rebuilds_its_glyph_geometry() {
let _fonts = fonts_steady();
let (mut d, id) = stroked_text_doc("A long story that must shrink to fit in a small area of type");
if let Some(Node { kind: NodeKind::Text(t), .. }) = d.node_mut(id) {
t.kind = TextKind::Area { frame: PathData::from_bezpath(&Rect::new(0.0, 0.0, 100.0, 45.0).to_path(0.1)) };
t.area.fit = AreaFit::ShrinkText { min_percent: 30.0 };
}
let opts = RenderOptions::default();
let mut r = Renderer::new();
r.render(&d, SIZE, SIZE, Affine::IDENTITY, &opts);
let first = r.texts.used_in(r.stamp).next().unwrap().1.clone();
if let Some(Node { kind: NodeKind::Text(t), .. }) = d.node_mut(id) {
t.xf = Affine::scale(1.2) * t.xf;
}
let scaled = r.render(&d, SIZE, SIZE, Affine::IDENTITY, &opts);
let again = r.texts.used_in(r.stamp).next().unwrap().1.clone();
assert!(!Arc::ptr_eq(&first, &again), "changing area type's scale lays it out again");
assert_eq!(scaled.pixels, Renderer::new().render(&d, SIZE, SIZE, Affine::IDENTITY, &opts).pixels);
}
/// Frames that draw character strokes from the cache draw the same pixels, and what a renderer
/// draws whose glyph cache has no room, so that it expands them in every frame: exactly at 100%,
/// where both take a tolerance of 1/4 device pixel, and within antialiasing at 105% and 150%,
+2 -2
View File
@@ -1,6 +1,6 @@
# Parity with Adobe Illustrator
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-06 · **Change:** minor (Properties in Edit Artboards: a Transform section with the reference point above the Artboards section, #5219; the Control bar's Stroke: and Opacity: links scrub their fields, #4088; an image zoomed in on is separated, colorized or proofed only where it shows (#4155); a document's first frame renders on the render worker, so opening a heavy file no longer freezes the window, #4155; Control bar Paragraph section with type selected, #5372; moving unchanged type reuses its glyph and character-stroke outlines; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-06 · **Change:** minor (Properties in Edit Artboards: a Transform section with the reference point above the Artboards section, #5219; the Control bar's Stroke: and Opacity: links scrub their fields, #4088; an image zoomed in on is separated, colorized or proofed only where it shows (#4155); a document's first frame renders on the render worker, so opening a heavy file no longer freezes the window, #4155; Control bar Paragraph section with type selected, #5372; translating unchanged type reuses its glyph and character-stroke outlines; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
## Feature submission evidence
@@ -31,7 +31,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard
| Date | Change | Summary |
|---|---|---|
| 2026-11-05 | minor | Moving a type object without changing its text or formatting reuses glyph geometry and expanded character-stroke outlines between frames. The moved text appears at its new position with unchanged pixels, and edits to text or formatting still rebuild the outlines; scores and estimates unchanged. |
| 2026-11-05 | minor | Translating a type object without changing its text or formatting reuses glyph geometry and expanded character-stroke outlines between frames. The text appears at its new position with unchanged pixels. Scaling the type, editing its content or formatting, or changing installed fonts rebuilds the geometry; scores and estimates unchanged. |
| 2026-11-05 | minor | Canvas: an image drawn larger than 1,024 pixels at the size it shows, with its colours made again (separated into ink planes, colorized or shown through Separations Preview), has them made only for the 1,024-pixel tiles in view, each kept for later frames (#4155). Zooming in to 50%, 100% and 200% on the file of #4155 went from 8.6–9.0 s to 0.78 s, 0.05 s and 0.05 s (measured, M3 Pro, one run each), with the same pixels. Scores and estimates unchanged. |
| 2026-11-05 | minor | Canvas: a document's first frame (opened, or its tab chosen) renders on the render worker instead of the UI thread; the window shows the document's paper and artboards until the art lands, and a frame ready within 16 ms shows at once. Opening the file of #4155 kept the UI thread busy for 8.7 s at a stretch, now at most 64 ms; a 50,000-path SVG 1.4 s, now 62 ms (measured, M3 Pro, one run each). Scores and estimates unchanged. |
| 2026-11-05 | minor | Canvas: an image drawn reduced in a CMYK document is shrunk to the size it shows before it is separated into ink planes, not separated at full size and then shrunk (#4155). On the 141-megapixel image of #4155 the first frame went from 9.2 s to 1.6 s, and the sharp frame after a pan from 3.9 s to 8 ms (measured, M3 Pro, one run each). The same pixels show within 5 levels; fine detail such as 1-pixel lines now shows its true average. Scores and estimates unchanged. |