Culling grew an object's box by its unscaled stroke and effect outset,
so a view or repaint patch that showed only the outer part of a scaled
object's stroke or hardened glow skipped the object. Culling now scales
both by the object's largest scale factor, as drawing does. The CMYK
ink-pass area grows each object, and each nested child, by its stroke
and effect outset under its full transform.
Decoding a placed raster built a second full-size pixel vector from the
RGBA image and premultiplied every pixel into it. The pixels are now
premultiplied in place, opaque pixels are skipped, and the buffer becomes
the pixmap's pixels without a copy (bytemuck's cast_vec, with a copy when
the capacity is not a whole number of pixels). The rendered SVG path
reuses its buffer the same way. For a 6000 x 4000 opaque image the step
takes 7 ms instead of 120 ms, with identical pixels.
A placed JPEG drawn at a fraction of its pixel size was decoded at full
size first and then halved down to the level the screen needs. For a
24 MP photo that is a 96 MB decode per image, and with several such
images on a page the decoded pixels outgrow the image cache.
A YCbCr or grayscale JPEG whose wanted level is a half, a quarter or an
eighth of its size (or smaller) is now decoded at that size straight
from its compressed blocks with jpeg-decoder's scaled IDCT, cut to the
size the halving path gives the same level, and halved from there for
smaller levels. The embedded ICC profile is applied as in a full
decode. CMYK and YCCK JPEGs, other formats and the full size still
decode in full.
The spread of a drop shadow or outer glow is stroked through the item's
transform, so on a scaled item it reaches that much farther. Damage now
grows the effect outset by the item's largest scale factor, and the
multithreaded renderer crops the effect's offscreen image to the scaled
reach, so the outer part of the glow is no longer cut off.
The coverage was eroded by sampling two rings of points, which could miss a hole smaller than the gaps between them. Erosion now takes the smallest alpha within an octagon of the band's radius, in four passes along the axes and the diagonals.
Both shifted copies are the same at distance 0, so the coverage mask is empty. The effect is now skipped before the image is drawn offscreen and scanned.
Satin on a frame holding a graphic draws the object's coverage once
offscreen and compares the two shifted copies pixel by pixel, taking the
difference of their coverages. A partly transparent area that both copies
cover equally gets no plain satin, so a uniformly half-transparent image
no longer shows satin across its middle. Inverted satin keeps the
object's coverage where the copies agree.
The offscreen coverage for satin and for a center inner glow on a graphic
now covers its whole area at a lower resolution when it would be wider
than the largest raster side or hold more than 4096 x 4096 pixels.
Inner glow from the center on a frame holding an image filled the
frame's shape, so it painted over the transparent parts of the image.
It now draws the object's coverage once offscreen, shrinks it by the
glow's band, colors and blurs it, and keeps the result to the painted
pixels. Partly transparent pixels keep their coverage.
With more render threads than bands of 32 rows fit evenly, the rows split
into fewer bands than requested, and the returned count was the requested
one. It is now the number of bands converted.
Satin on a frame holding an image used the frame's shape. Where the
image is transparent, the satin color multiplied over whatever lay
behind the frame, so text under a transparent part of the image turned
darker. Satin now builds its two offset copies from what the object
paints and keeps the result to the painted pixels, as the inner shadow,
inner glow and bevel already do.
The edge comparisons pass when a bevel or inner glow is not drawn at all.
A pixel inside the bevel and glow bands now has to differ from the same
object without the effect, for every feather kind.
A basic, directional or gradient feather faded only the object's body. Its
bevel, inner glow, inner shadow and satin were drawn afterwards over the
whole shape, so where the feather let the page show through, the bevel's
highlight and the inner glow screened whatever lay behind the object.
Text under the feathered edge of a beveled frame turned lighter until the
frame was moved off it.
Each inner effect is now faded by the same feathers before it blends with
what is behind the object, so a feathered object fades to transparent at
its edge with its effects.
A view turned 90 degrees with the frame turned back draws the shadow
again and matches a fresh render. Renders served from the CMYK viewport
snapshot drop kept images unused for 256 renders.
In the CMYK blend space view (Proof Colors off) every render converted
each pixel of the ink passes' area from the blended inks to a screen colour
on the calling thread, through a 16-entry lookup per pixel. With render
threads it now converts bands of rows on that many threads at once, at
least 32 rows a band. The colours are the same; the Wasm build and
single-threaded renders convert on one thread as before.
The canvas drew and blurred every drop shadow and outer glow on every
render, also when the object or the view had only moved. Each image is now
kept per object, effect, page and ink pass, with the whole effect drawn
once. While the object (apart from its position), the effect, the view's
scale and rotation, the render options and the document's colours, styles,
layers and images stay the same, a move by whole device pixels places the
kept image again. Any other change draws it afresh.
Only multithreaded renders (the canvas) keep images, and only for objects
without text or nested items. Kept images are limited to 4 Mpx each and
128 MiB in all; the images used longest ago go first, and an image no render
placed in 256 renders is dropped.
Damage treated any object with an effect as unbounded, so every drag step
of a frame with a drop shadow, outer glow, feather or inner effect rendered
the whole canvas again. An object's own effects are now bounded: the drop
shadow and outer glow by the reach the renderer draws them with, the inner
effects and feathers by the shape. Effects on items nested in a group still
repaint everything.
Strokes are drawn through the item's transform, so the stroke allowance now
scales with it, and the strokes of a group's children count toward the
group's area.
A JPEG whose EXIF resolution is 0 ppi or outside 1 to 100,000 ppi now
takes its size from its JFIF density instead of one point per pixel.
Tests place an 11 x 17 in image (330 x 510 px at 30 ppi) with a click,
check that it comes in at 792 x 1224 pt and keeps that size through a
save and reopen, and that an image with no stored resolution comes in
at 72 ppi.
* Render: a blur size is clamped to 1,000,000 pt before the filter planner squares it
* address review: bound effect extents and sigma before spread, padding and reach arithmetic
* fix: index style, font, class and layer name lookups in exporters and importers
* Apply review fixes
- crates/epub/src/css.rs
---------
Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
* Fix Links panel stalls on network paths
* Fix Links review findings
* Fix Links worker gating and wasm build
A link check blocked on another document's unreachable share no longer
holds back the document now shown: after 200 ms a fresh worker takes
over (at most four alive at once) and the stale result is dropped.
relinked_asset used the native-only fingerprint_from, breaking the
wasm build; it now uses fingerprint_of. The EPS relink and IDML link
reach tests build Windows paths correctly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Fix Links worker repaint and graphic read retry
Switching documents before the 200 ms takeover now schedules a repaint
for it: a blocked worker never asks for one, so without other input the
panel kept waiting. A failed graphic read is no longer cached as
missing, so the next check reads again. The legacy EPS fixture clears
its source fingerprint, as documents from before fingerprints have
none, so the test no longer depends on running within two seconds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep touched links OK and poll Links within seconds
Only a new size now marks a graphic Modified from its fingerprint. A
file with the same size but a new time (saved again, copied, restored
or checked out) is compared byte for byte, once per new time, and stays
OK when unchanged.
External changes are polled every two seconds instead of every five
minutes. The next check waits at least as long as the last one took
(up to five minutes), so a slow share stays idle half the time.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Wake Links when a worker slot frees; translate check strings
A worker thread asks for a repaint when it ends, so a document waiting
at the four-worker limit gets a worker as soon as a superseded one
returns from its blocked call, without other input.
Rows from a check keep a weak reference to their document. The key
names it by address, which a later document can't reuse while the
allocation is kept.
The Links panel's new strings ("Checking", "Checking links…", "Link
status is unavailable.") use the UI's ellipsis and are translated in
every interface language. The comments on Session::text_link_checks and
on the byte comparison in links::status describe what they do now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Links: rows from the document, statuses from a check that can stop
The panel lists links from the document on the UI thread (no file is
looked at) and fills in the statuses a worker check last found, kept
per document. An edit shows at once, and a check of an earlier edit
still supplies statuses instead of being discarded.
- A check of another document is told to stop and ends before its next
file; only one blocked in a file system call is replaced, so blocked
workers no longer hold their slots for a whole document.
- Checks are timed on the worker, and what they remember passes to the
worker that replaces them.
- A fingerprint is kept only for a file whose time was settled when it
was read, as for linked text. A file found unchanged by its bytes
gets its current size and time stored with the document
(remember_link_files), without marking a saved document as changed.
- Asset::set_link keeps link and fingerprint together; copies made by
Package and Copy Links To carry none.
- The Session holds one LinkListChecks. Update Link lists files only
when a linked story was edited in the layout.
- The unused "Checking links..." caption is removed.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
* An item a parent overrode and deleted is gone from the pages that use it (#1469)
In InDesign, removing an inherited item from a parent page means overriding
it there and deleting the override: the parent's page keeps the item in its
override list with no copy of its own. Only the page being drawn was checked,
so the pages that use that parent still drew the base's item -- a signature
block from parent B over the notice text of every page using parent E.
The override lists of the whole parent chain are checked, not just the page's
own. An override always names an item of a parent further back, so one set
covers the chain.
Rebased onto the post-split main: the parent-item loop moved from render's
lib.rs to draw.rs and the tests to tests.rs.
One thing this does not touch: blendspace.rs checks `page.overridden` the same
way in two places, for deciding which spreads hold transparency. A deleted
override there would count an absent item as present, which can only cost an
unnecessary flatten rather than draw the wrong thing, so it is left for a
maintainer to judge rather than widened into this fix.
* Parent items: one set of overridden items for drawing, PDF and PPTX export, hit-testing, snapping and frame edges
* Override All: an item a parent removed is not brought back as a copy
crates/ui-egui/src/effects_dialog.rs: kept both the angle dial tests (main) and the blend mode test (PR); the stray 'The dialog's body.' doc line moved back onto show.