Commit Graph
306 Commits
Author SHA1 Message Date
Dylan M. Taylor 49764b0b37 Merge main into reduced JPEG proxy decoding 2026-11-12 17:03:41 -05:00
Dylan M. Taylor 30752d0130 Merge pull request #2709 from dotCooCoo/fix/opaque-image-premultiply
Render: placed images are premultiplied in their decoded buffer
2026-11-12 17:01:32 -05:00
Dylan M. Taylor 7362fffbcf Merge pull request #2654 from dotCooCoo/fix/effect-damage-bounds
Canvas: moving an object with a drop shadow repaints only its area
2026-11-12 15:50:44 -05:00
dotCooCoo 6d8f26a6be Render: cull a scaled object by its scaled stroke and glow
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.
2026-11-12 12:48:49 -08:00
Dylan M. Taylor 6790d009fe Merge pull request #2651 from dotCooCoo/fix/placed-image-resolution
Place: images come in at the resolution stored in the file
2026-11-12 15:25:55 -05:00
dotCooCoo b0c9ce00aa Merge main into fix/opaque-image-premultiply 2026-11-12 12:25:31 -08:00
dotCooCoo 113319e3e1 Merge main into fix/jpeg-screen-proxies 2026-11-12 12:25:10 -08:00
dotCooCoo 8121bca1fe Merge main into fix/effect-damage-bounds 2026-11-12 12:24:21 -08:00
dotCooCoo ff12f718b6 Merge main into fix/opaque-image-premultiply 2026-11-12 10:53:49 -08:00
dotCooCoo 9f4a62776e Merge main into fix/jpeg-screen-proxies 2026-11-12 10:52:07 -08:00
dotCooCoo 8134e00ece Merge main into fix/effect-damage-bounds 2026-11-12 10:49:55 -08:00
Codex fe631061db Use mutable row iteration in render fixture 2026-11-12 19:49:14 +01:00
FredApps 113d196168 Merge pull request #2668 from dotCooCoo/fix/feathered-inner-effects
Render: a feathered object's bevel and inner effects fade with it
2026-11-12 19:40:26 +01:00
dotCooCoo 4e363e1bfa Render: placed images are premultiplied in their decoded buffer
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.
2026-11-12 10:29:50 -08:00
dotCooCoo d3a073470c Images: decode JPEG screen proxies at a reduced size
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.
2026-11-12 10:18:07 -08:00
FredApps 3bdae7cec1 Merge main and preserve PR #2668 behavior 2026-11-12 18:14:28 +01:00
FredApps 2348380198 Merge main and preserve PR #2663 behavior 2026-11-12 18:14:28 +01:00
FredApps 65dd56d7a6 Merge pull request #2671 from dotCooCoo/fix/satin-follows-image-edge
Render: satin and center inner glow on an image follow its painted edge
2026-11-12 18:06:50 +01:00
FredApps 04597b0652 Merge pull request #2657 from dotCooCoo/fix/keep-shadow-images
Render: keep drop shadow and outer glow images while an object moves
2026-11-12 18:06:07 +01:00
dotCooCoo f0f609a3ba Canvas: a scaled object's hardened shadow or glow stays in its damage
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.
2026-11-12 08:55:00 -08:00
dotCooCoo 092c46c148 Render: list layers among the kept shadow image's dependencies
The doc comment on with_kept_filters now names the document's layers next to its colors, styles and images, as Deps holds them.
2026-11-12 07:39:06 -08:00
dotCooCoo 5932810b1f Render: a center inner glow on an image fades around small transparent holes
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.
2026-11-12 00:04:46 -08:00
dotCooCoo 7af4d75539 Render: plain satin with no distance on an image is not drawn
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.
2026-11-12 00:00:46 -08:00
dotCooCoo c3a7deb21a Render: satin on an image compares partial coverage
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.
2026-11-11 23:23:50 -08:00
dotCooCoo 7a5924e971 Render: center inner glow on an image follows its painted edge
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.
2026-11-11 22:52:07 -08:00
dotCooCoo c9cc76e6ad CMYK view: the conversion returns the number of bands it converted
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.
2026-11-11 22:45:44 -08:00
dotCooCoo d20ffcc055 Render: satin on an image follows its painted edge
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.
2026-11-11 22:23:34 -08:00
dotCooCoo 23eb593498 Render: the feather test checks the inner effects still draw inside
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.
2026-11-11 22:18:21 -08:00
dotCooCoo 6854997294 Render: a feathered object's bevel and inner effects fade with it
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.
2026-11-11 21:53:45 -08:00
dotCooCoo 29f259bf07 Render: test that a turned view and snapshot renders handle kept shadows
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.
2026-11-11 19:54:23 -08:00
dotCooCoo 1fbb7e86b0 Merge #1084 (Alpha Channel text wrap) into main 2026-11-11 19:50:30 -08:00
autocraft-bot[bot] 229abafbe6 Apply review fixes
- crates/render/src/driver.rs
- crates/render/src/fx.rs
2026-11-12 03:43:53 +00:00
dotCooCoo 9c4c3730ab CMYK view: convert the blended inks to screen colours on the render threads
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.
2026-11-11 19:42:30 -08:00
dotCooCoo 4b06bb219c Render: keep drop shadow and outer glow images while an object moves
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.
2026-11-11 19:14:37 -08:00
dotCooCoo 0a8e9a5697 Canvas: moving an object with a drop shadow repaints only its area
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.
2026-11-11 18:56:30 -08:00
autocraft-bot[bot] 81f0d766cf Apply review fixes
- crates/images/src/resolution.rs
- crates/render/src/decode.rs
2026-11-12 02:47:57 +00:00
dotCooCoo c8136c538b Place: an unusable EXIF resolution falls back to the JFIF density
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.
2026-11-11 18:20:51 -08:00
Dylan M. Taylor 27d8eabb10 Render: clamp the blur size before the filter planner squares it (#2640)
* 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
2026-11-12 00:33:50 +00:00
Dylan M. Taylorandaiongg 15bea9fa7a Tagged Text, RTF, EPUB classes and PDF layers: lookups by set or map instead of list searches (#2212)
* 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>
2026-11-11 16:20:09 -05:00
Dylan M. Taylor ed3f45a57a render: cap the blend-area growth rounds, one name per optional-content layer (#2257) 2026-11-11 16:16:04 -05:00
9da88149be Fix Links panel stalls on network paths (#1444)
* 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>
2026-11-10 17:39:39 +01:00
Hamza Naveed 59501a26f9 An item a parent overrode and deleted is gone from the pages that use it (#1469) (#1558)
* 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
2026-11-05 22:22:47 +01:00
aiongg b1f67ee4e4 Merge pull request #2211 2026-11-04 04:14:12 +00:00
Dylan M. Taylor 64c956f09e fix(render): index line style groups, stop futile glyph-cache eviction, read PDF page sizes once (#2217) 2026-11-03 22:23:11 -05:00
Dylan M. Taylor edbea6036f fix: bound recent-file preview decoding and PDF crop allocation 2026-11-03 12:28:30 +00:00
NetterSilverandClaude Opus 5.5 001053e0dd Fix dotted strokes dropping most of their dots
Fixes #1950

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 03:07:22 +01:00
aiongg 7d16fffb39 Integration: #1451 screened outer glows and blended shadows isolate the spread from the paper 2026-10-31 00:35:26 +00:00
aiongg 0e4cb1f294 Merge PR #1451: Effects blend modes for Drop Shadow, Inner Shadow and Outer Glow
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.
2026-10-30 23:16:03 +00:00
moppeeerandClaude Opus 5.5 8c89bf5f1a rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 22:40:44 +01:00
moppeeer 3711ac05ba Merge remote-tracking branch 'origin/main' into effect-blend-modes
# Conflicts:
#	crates/render/src/fx.rs
2026-10-30 21:57:48 +01:00