The answer whether Fit to Artwork Bounds has art to fit moves from a
function-local thread_local to DocState, beside any_empty_artboards, and
drops with the document. It is kept for that version of the document
(held weakly, as any_empty_artboards holds its own) and the artboards
asked about, and measured again when the installed plug-ins, whose
effects draw art, or the installed fonts, which set type drawn by its
effects' art, change: their generations are an explicit input of the
measure. A change of the selection or the view keeps it.
The test counts the measures, as the Delete Empty Artboards check's
does: a later frame, select.set and a view change keep the answer; an
edit, other artboards, and each generation measure again. Taking any
part out of the key fails it.
fit_has_art kept its answer for the document's uid and revision, which
don't follow every change of what it measures: a document's tab coming
to the front replaces it with its composite fonts synced, and a plug-in
installed or removed changes what its effects draw, with no revision
moving either time. The answer is now kept for that document Arc, held
weakly as DocState::any_empty_artboards keeps its own, and the artboards
asked about, until the plug-ins' revision moves. A selection or view
change keeps it.
The test replaces the document with art on an artboard, its revision as
it was, and asks again: kept by revision, the answer was stale.
- A 3D effect that builds nothing: af754bcb2 said the object draws exactly
as without it under a Drop Shadow or Gaussian Blur. That holds only for
a stroked object. With only a fill, the raster effect draws from the
art made for the object, where without the 3D effect it is clipped to
the path, so Roughen's spikes differ: the earlier wording was right.
The test keeps the stroked cases exact and restores fill-only cases
with a Drop Shadow and a Gaussian Blur, which differ in under 4% of
the pixels and nowhere inside the path. Its reach check compares with
the object drawn without its raster effect, since Roughen alone
reaches past the path.
- The Vector Halftone test's bounds are a consistency check, and only
holding no art tests the branch: its doc no longer says no solid is
built (the free measure's halftone arm builds one). The overprint
test's area check is labeled likewise.
- Recoloring a traced shape bounds the area the renderer that drew the
trace object measures too, inflated by half the stroke and a pixel.
- The let-go test pins the nothing-to-draw branch: no frame, whole or
part, began since the measure.
- The parity doc's feature row names the stack overflow fix and its
test; a group test's doc says what its fixture holds.
Review follow-ups:
- The test that art measured for an edit not drawn on this thread is let
go first checks that measuring the edit through the canvas's renderer
holds art, so a measure that held nothing can't pass it. Its worker is
a test channel whose job the test receives, in place of a real thread's
pending job, which a finished frame could clear. Taking out either
let_go_of_measured fails it.
- fit_has_art's comment says why its one kept answer can't be stale: a
document's uid is never reused in the process and its revision only
moves forward.
Review follow-ups:
- The tests that a group with effects of its own is measured once a pass
plant its kept bounds after the first artboard and read them back over
the next two, so a measure made again fails. Its solid is built by the
free measure, which the renderer's three_d_built doesn't count.
- The budget test checks that every object, past the budget too, is
measured as the free measure does and draws as a new renderer draws it.
- A 3D effect that builds nothing draws the object exactly as without it,
with a Drop Shadow or Gaussian Blur too, which reach past the path. The
doc comment said those differ past the path; they don't.
- The brush widened in view first checks that the wider brush draws
otherwise.
- Recoloring a traced shape changes no more than the shape, its stroke
and a pixel's anti-aliasing.
Review follow-up: these three branches of what a renderer measures had no
test. Under Overprint Preview a renderer measures an edit as changed()
does and holds none of the 3D art it made for it; a 3D effect with
Vector Halftone is measured by the free measure, with no solid built and
no art held; and on screen in symbol editing mode, an edit to the
instance it was entered from changes nothing. Each test fails with its
branch taken out.
An image in a Separation color space opened as an RGB image: its spot ink
was lost (no plate in Separations Preview), and Fill and Recolor Artwork
didn't reach its color.
It now opens as a grayscale image of its tints (white where it lays no
ink, black at 100 %, its Decode array applied; 1 to 16 bits a sample, or
one gray channel from its JPEG, CCITT, JBIG2 or JPEG 2000 decoder),
colorized by its ink at 100 %: the spot swatch, a process plate's CMYK
color, or Registration. Its mask becomes its opacity mask, as a CMYK
image's does. The ink is found by the image's color space among those the
file defines, once per image. The ink None, an ink whose color can't be
told, images inside an alpha soft mask, inline images and DeviceN images
open as before; samples that can't be read open in RGB with a warning, and
the ink gets no swatch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The warning #6326 added listed the families `set_text` met while the
page ran. An Illustrator EPS can be rebuilt from its editing copy,
whose type may be in other fonts than the page's, and `stringwidth` and
`charpath` reach `set_text` without adding any type. The families are
now taken from the text objects of the document the import gives (its
layers and its symbols), once each, in the order the type comes,
whichever path built it.
Diff took the Image Trace flag of the old version for both sides when it
read each version's first member. Both versions have the same extras
there (same_but_members), so the result was right, but each side now
reads its own node.
The doc of Renderer's three_d_bounds now says what adds an entry, when
entries are swept, and the bound that follows: about twice the live 3D
art plus 1024 entries.
A mark glyph's vertical translation started a new draw_glyphs batch, so
krilla received the cluster's source range again and mapped its
characters twice. Copying or searching the exported PDF then found
doubled letters for Arabic harakat in any font, and for every dotted
letter in fonts that draw dots as zero-advance mark glyphs (Noto Sans,
Naskh and Kufi Arabic).
Keep compatible glyphs on the same layout line in one batch and carry
their relative vertical placement as per-glyph y_offset; horizontal
placement is unchanged (next_x - x advances). Font, size, linear
transform, line/column, paint run, list marker and hyphen boundaries
still split batches. Krilla keeps owning cluster mappings and
ActualText. No importer change.
Regressions decode the content stream and ToUnicode maps: one batch per
layout line, no duplicated cluster assignment, one ActualText per
multi-glyph cluster, contours within 0.05 pt of outline export; mixed
scripts, vertical columns, path rotations and PDF/X variants covered.
The reader round-trip stays an ignored test until the importer consumes
ActualText (#6165).
Addresses #6309.
Type set in a family that isn't available keeps its name and shows in
the fallback font, as in PDF import, but EPS import said nothing. It
now notes each such family once, in the order its type comes (at most
64), and ends with PDF import's warning: "fonts that aren't available
show in the fallback font until they are: <families>".
Tests that set type in fonts the test machine may lack (Helvetica,
Ryumin, made-up names) check the program's warnings without that note,
since which fonts are installed depends on the machine.
Found while testing crates/engine/src/cmd/graph/data.rs:45-47 (parse_csv)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A PDF image mask (`/ImageMask true`) painted in a solid color opened as an
RGB image with the color in its pixels: Fill and Recolor Artwork didn't
reach the color, a spot color lost its ink, and the same mask painted again
in another color took the first one, because the painted image was cached
by the mask alone, and so did an uncolored pattern whose cell draws a mask.
It now opens as a grayscale image of what it paints, colorized by that
color, as the .ai reader opens a 1-bit image mask (#5790). A spot color
keeps its swatch and tint. The page's walk counts paths, not images, so the
ink is found from the color space. Readings of a pattern cell are told
apart by colorized images' colors too. Inside an alpha soft mask, or
painted with a pattern, a mask opens as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
copyFrom only writes paints enabled for pickup and apply, and paint, Transparency and the Eyedropper record an undo step only when the override changes.
copyFrom still edits the part when reverse, append and defaultsOnly are false, and reverse copies onto source. transparency.set records an undo step only when the override changes.
A picked part takes transparency and the Eyedropper only when those calls omit their other targets. Art, Pattern and Bristle brushes, native Wayland and the web still do not take tilt, bearing or rotation.
A dithered fill or a Perceptual linear or radial gradient whose stops
are all CMYK was written as an RGB image. It is now a CMYK image.
The stops keep their inks, an off-center midpoint is halfway between
its two stops' inks, and a Perceptual curve uses the ink mixes a
DeviceN shading uses. Dither's noise is added per ink and adds no ink
where the gradient has none.
The Output settings convert the inks as they do for any CMYK image.
A gradient with an RGB, gray or Lab stop, a stop linked to a spot
swatch, or a Perceptual curve of more than 4,096 stops is still written
as an RGB image.
Direct Selection of a path, compound path or type inside a dynamic instance now applies transparency and gradient or pattern fills through the usual paint commands, and the G5 docs catch up on Overlap and Pattern auto corners.