The gate that limits parallel decodes counted each image at its cached
size (4 bytes a pixel and a third more for the smaller levels). A decode
holds more than that while it converts the pixels: an 8-bit image keeps
its RGBA copy beside the decoded or the premultiplied pixels, 8 bytes a
pixel. Two 5,500 pixel square images passed the gate together and could
hold more than half the cache budget at once.
- decode_sizes returns the cached size and the peak size from one size
read. The peak counts the samples as stored beside their converted
copy (designcraft_images::decode_bytes_per_pixel): 8 bytes a pixel for
8-bit color, 10 for 16-bit RGB, 12 for 16-bit CMYK TIFFs and 16-bit
RGBA, 10 for 8-bit CMYKA TIFFs, 15 for 16-bit CMYKA TIFFs, 9 for
PSDs. An EPS counts as its TIFF preview. PDF pages, SVGs and EPS
files without a preview count 8.
- warm budgets the cache with the cached size and gates decodes with
the peak size.
- Every warm call in the process shares one gate, so the canvas
worker, thumbnails and exports together stay within half the budget
while they decode. warm returns the most its own call had decoding.
- An EPS without a preview is sized at the larger of its drawn
PostScript and its placeholder. The placeholder is clamped to 4000
pixels on each side, so a 10,000 by 4,000 point EPS that is not drawn
takes 4000 by 4000 pixels, not the 4000 by 1600 counted before.
When the grid step nearest the centered place puts the lines outside a frame that narrows and widens again, Center now tries the steps on both sides of it, nearest first, instead of only the steps above it.
In a frame that narrows and widens again, Bottom, Center and Justify now
try lower grid steps until the lines fit the outline, and leave the lines
in place when none does, instead of taking the next lower step unchecked.
A grid whose step is too small to count across the column is now treated
as no grid when a line is placed, so the line keeps a finite baseline.
Tests cover a waist-shaped frame on a 40 pt grid, a tiny-step grid that
starts away from the line, and Justify with a wrapped paragraph under
All Lines and First Line Only.
Copying a story gives the objects anchored in its table cells and
notes fresh ids down to 64 levels, as the table copy does. A copy whose
stories below that level hold anchored objects, tables or notes is
refused with the nested-too-deeply error instead of recursing without
limit.
The JPEG decoder takes the smallest scale that meets either requested
side. A short side rounds up to the same size at several scales, so a
100 x 2 JPEG asked for at a half decoded at an eighth (13 x 1). The
long side alone now picks the scale, and a decode whose size differs
from the requested reduction is refused, which falls back to the full
decode.
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.
object::renumber now gives a story copy's anchors and tables new ids.
Duplicate Layer keys each copied anchor by the original anchor's id,
so copied cross-references point at the copied paragraph, and pairs
copied tables with the originals in order, so objects anchored in
table cells keep their live captions. A copy that renumber reports
incomplete is refused with the nested-too-deeply error.
A render decoded each placed image that was not cached yet while drawing it,
one after another, so page thumbnails, image exports and the first canvas
frame of a page with several large photos took the sum of their decodes.
Before drawing, the renderer now lists the images in view (with the same
culling as drawing: hidden items and layers, nonprinting items, items out of
view, PDF layer choices) and decodes the uncached ones on up to eight threads,
with the mip levels they are drawn at. It leaves the work to the render when
fewer than two images need decoding, on the web, and in Fast display. The
images it decodes stay within what the cache keeps, sized by their pixels
(PDF pages and SVGs at the size they are rasterized at), and decodes in
flight together stay within half the cache budget.
The one Inset field of a non-rectangular frame and the inset link now
follow the frames the dialog changes: the frame that shows the caret,
or every frame holding selected text. Before, a caret with no stored
frame showed four sides for an oval frame, and the link checked every
frame of the story.
A preview remembers the document it is shown in. When OK is refused or
Cancel is chosen after another document became active, that document
goes back as it was instead of keeping the previewed options.
The frames taken from the caret or selected text are also refused once
the document has changed after the dialog opened. Undo puts back the
document's id counter, so a frame made after Undo can take a stored id.