A manifest may list `permissions` (doc.read, doc.write, state,
effect.render, export.write) and an `api` level. doc.read, doc.write
and state follow the capability model proposed in
storytold/photocraft#662; the other names are VectorCraft's own. An
unknown, reserved, duplicate or wrong-kind name is refused by name. A
manifest without the key gets the permissions its kind implies and
installs as before.
- Install Plug-in... and File > Open show the name, id, version, file
SHA-256 and each permission in plain words, with control and
bidirectional characters escaped and each string cut to 64
characters. OK installs the module only if it still has the SHA-256
shown; Cancel installs nothing. The heavy-budget prompt and the
status line show the escaped name too, and OK keeps the `replace` it
was given.
- `plugin.install` needs `grant` listing every permission, and
`plugin.inspect` reports `needsApproval`. `hash` pins the module:
one with another SHA-256 is refused. The grant is kept with the
module's hash in the store's `grants.json`, and only that store's
grants count while it is attached; the same set does not ask again,
more permissions do, and `plugin.remove` forgets it.
- The Additional Plug-ins Folder and `plugin.reload` install only
plug-ins the attached store has granted and report the others as
needing approval. At startup the store skips an ungranted plug-in.
- A filter run without doc.read is given no objects; without state it
neither reads nor writes `documentData`; without doc.write an output
that changes the document is refused and the document is unchanged.
Docs: docs/plugins.md, docs/mcp.md, docs/target-app-parity.md.
An envelope mapped type from its laid-out box: ascent to descent for
point type, the frame for area type. The distorted glyphs then filled
less of the envelope than other art does, with room above the capitals
and below the baseline.
The envelope now maps type from the bounds of its glyph outlines,
underlines and strikethroughs when the type is on its own, in groups
and layers, or used as a clipping path. Inline graphics count by their
boxes. Rotated type and type in perspective map from their outlines as
they are drawn. Make with Mesh,
Make with Top Object and Reset with Mesh without Maintain Shape use
those bounds. Type that draws nothing keeps its laid-out box, and so
does type inside any other object, such as a blend, a repeat or a
symbol instance. Shrink Text to Fit type is measured as it is laid out
on the page.
vectorcraft-text's envelope_ink measures the type, and
register_envelope_ink registers it with the document crate. The engine
session, Renderer::new, live evaluation in vectorcraft-effects and the
.ai reader register it. The document crate keeps the measured boxes per
thread, by object and by a hash of the content, and measures again when
the type, the fonts, the hyphenation exceptions or the transform's
scale or rotation change.
This is VectorCraft's own rule. Envelopes of type made in VectorCraft
and in saved files map from the glyph outline bounds instead of the
type's laid-out box, so they redraw differently.
Holding a single-key tool shortcut becomes temporary: releasing it
returns to the previous tool (a quick tap still switches for good).
With the Pen chosen, holding S chooses Scale; letting go of S after
0.25 s or more, or after Scale was used while S was down, chooses the
Pen again. A press shorter than 0.25 s, with nothing done in between,
keeps Scale chosen as before. The 0.25 s threshold is VectorCraft's own
value. A Cmd/Ctrl click, which the selection tool takes, does not count
as using Scale. A drag of the Hand, Zoom or Rotate View tool chosen
this way counts as using it.
A key let go during a drag, with the pointer button held or with a
dialog open, goes back once that ends. A key let go while the tool
waits for its next click (the Dimension tool after its first point)
goes back once the tool finishes or is canceled. With S held from the
Pen and then V held, letting go of V returns to Scale, and letting go
of S then returns to the Pen. Choosing a tool on the toolbar or from a
menu while the key is down, the held tool included, ends the hold and
keeps that tool, and so does the window losing the keyboard.
While the preference is on, the key's repeats do not choose the tool
again.
The new General preference Hold a Tool Shortcut to Use the Tool
Temporarily (`holdToolKeys`, on by default) turns the behavior off.
With it off, every press and every repeat chooses the tool, as before.
Its label has a row in every catalog.
Docs: docs/mcp.md, docs/target-app-parity.md.
Commands that read `id` and otherwise act on the selection, the highlighted
layer row or a new object read it with a lenient helper, so `{"id": "abc"}`,
`true` or `{}` acted on the selection instead. They now read it with
`object_param`, which refuses any value that is not a non-negative integer
with "`id` must be a whole number" under the command's name and changes
nothing; an omitted or null `id` keeps the default.
Commands: object.isolate, layer.locate, layer.releaseToLayers,
graphicStyle.new and redefine, charStyle and paraStyle new, apply and
redefine, image.info, links.info, links.goTo, links.unembed, shaper.release,
shaper.expand (whose errors now carry their own name),
transparency.editOpacityMask, transparency.viewOpacityMask, symbol.edit, the
object.blend.spine commands, path.curvature and the type commands that read
type ranges.
targets() read `id` as an object only when it was a number. Any other
value ("abc", "5", true, {}, [1]) fell through to the selection, so a
command such as css.export, whose `id` the shared check does not read,
acted on the selected objects instead of failing. targets() now reads
`ids` and `id` through named_ids(): a value that is not a non-negative
integer is an error, and an omitted or null `id` still means the
selection. A numeric string is refused, as it already is in `ids`.
effect.apply and appearance.addEffect accept the effect as `id` when
`effect` is left out; they now read their targets with that `id` set to
null, so the effect still applies to the selection as before.
The panel opens from Window › 3D and Materials (window.panel {panel:
"threeD"}). Its object types Plane, Extrude, Revolve and Inflate apply
Rotate, Extrude & Bevel, Revolve or Inflate to each selected object
without a 3D effect, and change the 3D effect of each other selected
object in place, all as one undo step. Below them are the effect
dialog's Object, Rotation and Lighting tabs with the same controls.
A changed setting goes to every selected 3D effect that takes it, as
one undo step; a drag previews and records one step on release, and a
change of selection during a drag commits it first, and so does closing
or hiding the panel. A setting the
selected effects hold with different values shows its default with its
reset dot filled. A light list edit reaches only the objects whose list
matches the first object's.
effect.setParams takes threeDType (plane, extrude, revolve, inflate):
the settings both effects take keep their values, rotation angles wrap
into -180..180 outside Revolve, and the rest start at the new effect's
defaults. Another value, or a non-3D effect at index, is refused; the
type an effect already has, with nothing else to change, records no
undo step.
Materials, shadows and ray-traced rendering are not part of this.
Docs: docs/three-d.md, docs/mcp.md, docs/effects-parity.md,
docs/target-app-parity.md.
Fixes#3672
document.open, file.place and document.pdfInfo read cropTo (and its
older name crop), password, colorMode and textAs as strings and used
the default when a value was not a string, so "textAs": true or
"colorMode": 5 opened the file with the defaults. They now return an
error naming the param, and nothing opens or is placed. A wrong crop is
refused even when cropTo is given. document.pdfInfo also rejects a
thumbnailSize that is not a number, with or without a thumbnail.
Leaving a param out or giving null keeps its default, and an empty
password still means no password.
charStyle.load, paraStyle.load and textStyle.loadAll imported the styles
into a copy of the document to see whether anything changed, then ran the
same import again inside the edit. The edit now takes the copy the first
import made. While a typing session is open the import still runs inside
the edit, because the edit ends the session first and that can change the
document.
Matching a loop of definitions parsed the document's brush library again
for every comparison, and placing brushes in use order parsed it again for
every brush. Each now reads it once.
The params text and docs/mcp.md now say that the symbols and brushes the
patterns use come along, that `skipped` lists names in the file, and that
charStyle.load and paraStyle.load list only the styles of their own kind.
When the document has a loop of styles and patterns under one set of names, its styles
were still matched one by one, so a style could be matched to another copy with the same
attributes and the pattern then compared with the wrong style name. Each definition of
such a loop is now the document's under the name found for it.
A brush whose art sets type in a style renamed on the way in was compared before the
rename was known, so loading the file again added the brush and what uses it again.
Loading now places brushes with the styles, symbols and patterns, each after what it uses.
Paste keeps its order.
A style that paints with a pattern whose type is set in that style could be matched to the
document's style of the same name and attributes while the pattern came in under a free
name, so the loaded style painted with the document's other pattern. When the document does
not have such a loop under one set of names, each of its styles, symbols and patterns is now
added.
The names a loop of styles and patterns has in the document were searched by trying every
combination, up to 256, so a loop of nine with a numbered copy each was not matched and a
repeat load added it again. The names are now picked one definition at a time, comparing each
definition as soon as the names of those it uses are picked.
A loaded character style kept a size, scale, leading, shift or stroke width that
charStyle.new refuses. Such a style is now skipped and listed in the reply's skipped names.
Load Character Styles and Load Paragraph Styles left out every style of the other kind,
so a pattern that a loaded style paints with kept a reference to a paragraph or character
style the document did not get. The styles of the kind not loaded now come along when such a
pattern or symbol sets type in them, renamed like any other.
The order in which styles, symbols and patterns are placed is worked out from one graph of
their uses instead of scanning every definition left in each round.
Loading styles placed every definition in a loop of uses, and everything that used one, in one group and tried the product of all their candidate names under one cap of 256. Separate loops multiplied: nine self-referencing patterns, each in the document under its name and as a numbered copy from an earlier load, gave 512 combinations, none were tried, and a repeat load added more numbered copies. One loop with no candidate stopped every other loop from matching.
The loops are now the strongly connected components of the uses among those definitions. Each loop is matched with its own search and cap, and a definition that only uses a loop is placed after it, with the loop's names known.
The Character Styles and Paragraph Styles panel menus get Load Character
Styles... or Load Paragraph Styles..., and Load All Styles..., which add the
styles of a document picked in an open dialog in one undo step
(charStyle.load, paraStyle.load, textStyle.loadAll). The swatches,
patterns and symbols the styles use come along as Paste brings them, in
use order, so a style or pattern renamed on the way in keeps its links.
A style the document already has, under its name or a numbered copy of
it, is not added again; another style whose name is taken is added under
a free name. The file's Normal styles, and styles with a blank name or
attributes that do not read, are not loaded.
Smooth Color now counts the steps between each pair of keys from the
keys' colors and visible bounds, which changes the step count of most
Smooth Color blends. The counts are VectorCraft's own values:
- When the keys' solid fills or strokes differ (in groups, member by
member; in text, run by run), the count is 255 times the largest
change of one channel as a fraction of its range, a half step
rounding down, from 1 to 254. An RGB channel's range is 256 values,
CMYK and gray count in percent, and two tints of one swatch by their
tints. It is at most eight per point of the largest of the keys'
widths and heights and the distance between their centers. Black to
white was 128 steps and is now 254.
- When the colors match, a solid paint meets no paint, or a key holds
a gradient or a pattern, the count is the largest distance between
corresponding visible bounding-box edges divided by the keys' mean
width or height, rounded, less one, from 1 to 1000. Two 20 pt
squares 200 pt apart were 100 steps and are now 9.
Keys without bounds make the color count when their colors differ,
and 1 step otherwise.
A blend nested in another blend's keys counts toward the step limit
by its color steps when its colors differ, and as up to 1000 steps
when they match (256 before). An outer blend of 200 steps between two
such same-color Smooth Color blends now draws 99 steps.
A Smooth Color blend in an .ai file whose drawn steps follow this rule
now opens as a live blend.
Blend Options: https://web.archive.org/web/20241217212108/https://helpx.adobe.com/illustrator/using/blending-objects.html
Docs: docs/mcp.md, docs/target-app-parity.md.
A non-null `colors` that is not an array now gives "`colors` must be an array of colors, not ..." instead of the generic "bad color ...", with a row in every catalog. The loadProfile and removeProfile refusal tests also check that no profile is loaded or removed and the settings are unchanged.
A colors value that is not an array, such as "#fff" or 5, was ignored and the command checked the selection or the whole document instead. It is now an error. A null colors still checks the selection or document, as an omitted one does.
The color management commands read their params with helpers that fell
back to the default for a value of the wrong type, so "bpc": "no" kept
the old setting, "on": "true" toggled the view and "convert": "no"
converted the colors. They now go through switch_or and text_param:
such a value is an error and nothing changes. Omitting a param or
giving null keeps its default.
- edit.colorSettings: rgb, cmyk, intent, bpc
- file.documentColorMode (and its alias): convert, intent, grays,
checked before the early return for the current mode; PDF import's
grays reads the same way
- color.convert: to, intent
- color.loadProfile: path; color.removeProfile: name
- view.proofSetup: target, intent, simulatePaper, proof
- view.proofColors and view.overprintPreview: on
- view.separationsPreview: on, only, toggle, and plates, which must be
an array of plate names
- swatch.setSpot: name, spot
With an unclipped raster/vector balance between 0 and 100, a group that
splits into more than 10^(balance/20) regions is rasterized whole and
none of its regions are used. The region build now stops at the first
region past that limit (pathops `regions_within`) instead of building
every region and then discarding them. Groups at or under the limit,
and every group with Clip Complex Regions on, still build every region.
Flatten Transparency, the flattened document and EPS export come out
the same as with every region built, for groups under the limit, at it,
just over it and far over it.
A corner tile was turned so that its x axis followed the mean of the
directions the path arrives and leaves in. A tile drawn as a right-angle
corner then came out turned 45° at every corner, so a rectangle drew its
corners as diagonal chevrons.
Outer and inner corner art are now both read as the corner that joins a
side tile on its right to one below it, as in the help's steps for
making corner tiles. Each corner tile is turned so that those two arms
meet the sides: on a rectangle the tile is square to the side tiles and
turns 90° from one corner to the next, and at other angles it is turned
halfway between the two sides. The arms follow Flip Along and Flip
Across, and a corner that takes the other kind's art turns it the same
way. Which art each corner takes is unchanged.
The PatternBrush field docs, the brush.options params text, docs/mcp.md
and the progress doc describe how corner art is drawn.
object.envelope.makeWithWarp, resetWithWarp and options read `style`
and `orientation`, and options read `preserveShape`, as text and
ignored any other value, so `{"style": 5}` kept the default style and
`{"orientation": "diagonal"}` kept the current orientation. They now
return "`style` must be a string" or "`preserveShape` must be a
string" for a value other than text or null, and "`orientation` must
be one of horizontal, vertical" for any other orientation, through
the shared `choice` helper. object.envelope.options checks the warp
keys whatever is selected, so a call with no envelope or only mesh
envelopes selected gets the same errors, an unknown style name
included. Omitted and null values keep today's defaults.
Docs: docs/mcp.md, docs/target-app-parity.md.
On open, a link found away from its path was passed to the same file's links in symbols, graph designs, patterns and opacity masks only when the nested link equaled the layers' link field for field. A nested link without a relative path, as documents saved before kept them, then kept the old path. The new path now goes to every nested object that shows the same file and content.
Update Links, and opening a document with Update Links: Automatically,
now read a modified file again for the images and placed documents in
symbols, graph designs, patterns and opacity masks that show the same
content as the objects read in the layers. By default Update Links also
reads the files that only that art shows. Each nested object takes the
file's place as its own Placement Options say, including the clip, and
its link takes the new path, size, modification time and hash.
Saving a document also refreshes the placed copies of it inside symbols,
graph designs, patterns and opacity masks of the other open documents,
not only those in the layers.
Relink, Embed and Unembed still change only the objects they are given.
A save wrote the path relative to the document only for linked images and
placed documents in the layers. Links inside symbols, graph designs,
patterns and opacity masks kept only their absolute path, so after the
document and its files moved to another folder together, those files were
not found.
- The save sets the relative path of every link the document holds.
- On open, a link inside that art whose file was found away from its path
takes the new path, as a link in the layers does, so the next save
writes the right relative path.
- Document::update_links_where changes only the links it picks and copies
only the nodes on the way to them.
Docs: docs/mcp.md (Linked images), docs/target-app-parity.md.
With Fade Region Outside Artboard on, the canvas now draws the fade over the
art as well as the pasteboard: one mesh of black at 40% opacity covers the
canvas outside the artboards, so the pasteboard and any art on it show each
channel at 60% of its value, and art inside an artboard is unchanged. It
replaces the darker pasteboard fill.
Artboard Options sets the Global checkboxes' preferences only after
artboard.setProps or artboard.new succeeds. When the artboard command
refuses a value, the preferences stay as they were and the dialog stays
open. A Global value that is not true or false is refused before anything
changes.
Docs: docs/mcp.md, docs/target-app-parity.md.
Artboard Options gets a Global group with Fade Region Outside Artboard and
Update While Dragging. Both are application preferences
(fadeRegionOutsideArtboard, artboardUpdateWhileDragging), on by default and
also listed under Preferences > General > Artboard Options.
While the Artboard tool is active, the canvas draws the pasteboard with each
color channel at 60% of its value. With Update While Dragging off, the
pasteboard draws as usual while the tool moves or resizes an artboard and
darker again when the drag ends. Exports and print do not change.
Docs: docs/mcp.md, docs/target-app-parity.md.
Find and Replace, Find Next, Change Case, Smart Punctuation, Insert
Character and Type on a Path Options read their params with helpers that
fell back to the default for a value of the wrong type: Find and Replace
with `replace: 5` replaced every match with nothing, and `flip: "true"`
did not flip. They now return an error and leave the document, the
selection and the undo history unchanged:
- `find`, `replace`, `case`, `char`, `text`, `unicode`, `effect` and
`alignToPath` must be a string or null.
- `matchCase`, `wholeWord`, `dashes`, `ellipsis`, `quotes` and `flip`
must be true, false or null.
- Smart Punctuation's `scope` must be `selection` or `document`.
- Type on a Path Options' `spacing` must be a number or null.
- Insert Character's `code` must be a whole number or null.
- Find and Replace's `ids` must be a list of existing object ids.
Insert Character checks `char`, `text`, `code` and `unicode` before it
picks one, so `{"char":"bullet","unicode":176}` is refused too. The
order the sources are used in is unchanged. Null counts as left out, so
`type.insert {code: null, unicode}` inserts the Unicode character.
Omitted params keep their defaults.
Recent Colors now keeps up to 30 solid colors instead of 10, newest
first and each once; applying a 31st drops the oldest. The Session
holds the list, so it stays the same when another document is opened
or made active, and it lasts for the session.
The Color and Swatches panels wrap the chips onto further rows when
the panel is too narrow for one row, so every color can be clicked.
A list that fits one row draws as before.
Docs: paint.recent params text, docs/mcp.md, docs/target-app-parity.md.
Images were keyed by their bytes alone, so two <image> elements that
link different files with the same bytes shared one image key. Every
missing file shows the same placeholder, and files can also be copies
of each other. Export reads a linked file's pixels into the image key
when the document holds only a preview, so once one of the files was
found or changed, the images of the other file exported and printed
that file's pixels.
A linked image's key now also holds a hash of its link's path, as the
.ai reader's linked images do. Images of one file still share a key.
The missing-file placeholder comes from
vectorcraft_doc::links::missing_placeholder instead of a copy in the
SVG importer.
Reset Bounding Box set the angle to 0 on the selected objects only. A
rotation changes the box angle of the selected objects and of every
object inside them, so the members of a rotated group kept their angle:
after rotating two rectangles 20 degrees, grouping them, rotating the
group 10 degrees and resetting, Ungroup brought back a box at 30
degrees, and a second reset reported 2 objects to change.
The command now also squares every object inside the selected ones: the
children of groups, compound paths, clip groups, blends, envelopes,
repeats and intertwines, and the art of linked opacity masks. The art of
an unlinked mask does not turn with the object, so it keeps its angle.
Ungroup, Release Clipping Mask, Release Compound Path, Blend Expand,
Release Envelope, Release Repeat, Release Intertwine and Release Opacity
Mask then bring back boxes square to the page. The whole reset stays one
undo step.
Two results change. `changed` counts every object reset, the objects
inside included, so the steps above return 3 where they returned 1. A
group whose own box is square but whose members are turned used to
return 0 with no undo step; it now squares the members in one step.
Docs: params text, docs/mcp.md, docs/target-app-parity.md.
Preferences > Smart Guides gets Snap to Last Location (`snapToLastLocation`,
off by default). With it and Smart Guides on, a selection moved by dragging
with the Selection, Group Selection or Direct Selection tool, Shift too, goes
back to where the move began while the move is within Snapping Tolerance,
labeled "last location". An Alt copy is not pulled back onto its original.
Source: https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/smart-guides-options.html
The distance, the label and the copy rule are VectorCraft's own.
An instance in perspective selected with a turned instance stays as it
was while the other is reset and returned in one undo step. Stored
natural sizes that are negative on either side give the art its own
size, unmirrored, as a zero size does.
The Symbols panel menu's Reset Transformation and the Control bar's Reset
(shown while symbol instances are selected) give the selected instances
their symbol's own scale again, without rotation, shear or reflection, as
one undo step (symbol.instance.resetTransform). Each instance keeps the
center of its art's bounding box in place. Instances in perspective and
instances already at their symbol's scale are left as they are, no undo
step is added when nothing changes, and both controls are enabled only
while a selected instance would change.
Docs: docs/mcp.md, docs/target-app-parity.md.
Three tests failed on a loaded machine because they asserted elapsed
time. Each now counts the work that the slow behavior it guards
against would repeat, with a counter compiled only into tests:
- The CSS cascade test counts selector tests, at most two per element
(testing every rule against every element tests N x N). It styles
5,000 elements, so the slow behavior fails on the count rather than
on the hang guard, which now waits 300 s.
- The stacked-glow test counts the silhouettes drawn, 30 for 30 glows
with and without the shadow cache.
- The Zstandard frames test counts the bytes looked at to find the
zero padding.
The hang guards for invalid dash patterns, text layout and script
checks of a pipe wait 300 s instead of 20 s.
The History panel gets a New Document from State button at its bottom,
which runs the new edit.newDocumentFromState command. The command makes
a new document holding the art of a History panel row ({index?}, the
current state when omitted) and makes it the active document. An index
that names no state is an error and changes nothing.
The new document takes the next Untitled-N name, is marked unsaved, has
nothing selected, no steps to undo or redo and no modified date, and
leaves symbol, opacity-mask and pattern editing; the art drawn in a
pattern's tile is stored in the pattern, as Done stores it. Its links point at the files the
source finds, including files found in the source's folder away from the
links' paths. Those files are looked for only within the folders the
asking caller may read; for a caller without limits, within the folders
the caller that opened the source may read. The source
document, its steps and its saved state stay as they are; typing or a
drag in progress is first kept as a step, as Undo keeps it. While an IME
composes, the command waits, as Undo does.
Docs: docs/mcp.md, docs/target-app-parity.md.
The mesh tests now count each feedback path's subpaths, so a mesh that
drew its boundary instead of its mesh lines fails them. The progress-doc
lines name the Pathfinder, mesh and symbol instance outlines and the
limit's count of evaluated objects.
With Real-time Drawing and Editing off, each pointer move of a drag ran one
boolean union of a group's members to draw its outline. A group of 256
overlapping ellipses took seconds per move, and at 1,024 overlapping ellipses
the union went over its budget and no outline showed.
A move or handle drag now draws the outline of each visible member of a group
or intertwine, and of each object a blend, envelope, repeat, Pathfinder effect
or object effect evaluates to, without uniting them. A gradient mesh draws its
mesh lines and a symbol instance its bounds, as their selection highlights do.
The limit of 100,000 counts outline points and evaluated objects, so a
selection past it shows its moved bounds.
A compound shape or Pathfinder effect still evaluates its boolean on each move,
and so does a clip group whose clipping path is a group.
appearance.addFill, appearance.addStroke and appearance.duplicateItem can
put a new topmost row on a series mark with the paint the mark already
shows. When another mark of the series had set a different stored paint,
the mark's top paint did not change, so the graph kept the other mark's
paint and drew it again. A new topmost visible row now stores its paint,
as an Eyedropper append already does.
The Appearance commands do not store a stroke paint or weight for a series
that draws a Filled Lines band, but they do store a stroke opacity set on the
band, and the band's 0.25 pt black outline takes it when the graph is drawn
again. docs/mcp.md now says so, and a test covers it.
The params text of the Appearance commands that update a series' stored
paint said the graph stores the paint and weight of the topmost visible
fill and stroke. Each of them also stores that row's opacity, as
docs/mcp.md says. The text now names the opacity too.
paint.setFill, paint.setStroke, paint.none, Apply Fill to Stroke and Apply
Stroke to Fill stored a series' paint on the graph. appearance.setItem, the
Eyedropper, appearance.transfer, Clear Appearance, Reduce to Basic Appearance
and the add, remove, move and duplicate row commands stored no paint or weight.
An Eyedropper pick of a blue fill at 40% onto a red column drew red at 40%
after the next redraw.
These commands and Show All Hidden Attributes now store the paint and weight
of the topmost visible fill and stroke of a path directly in a series group,
in the same undo step. A color, weight or opacity that a command writes to that
row replaces the stored value even when the mark's own value does not change. A
row that has no paint before and after the command does not change the stored
paint. These commands store no stroke for a series that draws Filled Lines
bands, and a band no longer takes its color from an empty stored stroke.
The stored opacity also comes from the topmost visible row: hiding a top row
stores the row under it, and an opacity set on a hidden top row is not stored.
Follows #5501.
Choosing a PDF/X standard without a PDF/X preset writes a file with no bleed
(BleedBox = TrimBox) even when Document Setup sets one, and the export gave no
warning about it. The export now warns when a PDF/X file has no bleed on a side
where the document's bleed has one. The warning comes ahead of the flattening
note, because the status bar shows only the first warning. The code adds a
warning and does not change what is written.
These cases do not warn: the PDF/X presets, Use document bleed settings, a
nonzero bleed on every side the document sets, a document with no bleed, files
that aren't PDF/X files, and Export for Screens rows whose artboards Include
Bleed grows.
The warning has a row in every catalog. The Summary's warning and error rows in
the Save PDF and Print dialogs now go through the catalog, so they show its
translations.
The Shape Builder, Live Paint and run_around tests in planar/tests.rs
measured elapsed time against a 5 s limit, and the large edit tests
(large_edits.rs, with the Lock and Hide All Artwork Above and perspective
Alt-drag tests that share `soon`) against 20 s. On a loaded machine they
failed without any change in the code.
- pathops: a test-only counter adds up the items `RectIndex::at` reads
and the segments `nearest_u` searches. The four planar tests assert a
bound on that count.
- doc: `tree_walks` counts, per thread, the walks of a document's tree
that lookups by id make. `soon` fails when a command walks the tree
more than 64 times, and keeps a 300 s wait for a hang. The tests that
named a 20 s limit are renamed.
Looking objects up one at a time in Delete or Offset Path, or scanning
the whole index or ring in the planar code, makes these tests fail.
Opening a document laid out every type object for its bounds and
baselines and threw the layouts away, and the first frame laid the same
objects out again. The open now keeps them, up to 128 MiB, and a frame
takes each one once.
A frame takes a layout only for a text object equal to the one laid out,
and only while the fonts, the system fallback setting and the hyphenation
exceptions are unchanged. When the last frame being drawn ends, the rest
are dropped if a frame took one, and all of them are dropped after eight
frames that take none. A layout with bitmap or color glyphs and a text
object with a gradient are not kept.
A paste relinked every copy to the document's resources even when no
resource had another name or color and the objects linked no graphic
style. It now leaves those copies as they are.
Finding the pasted type looked each id up and compared every text object
with the ones already found. Text commands and the bounds refresh after
a paste now look all ids up in one walk and keep the found ids in a set.
Giving a pasted group new ids builds its map of old to new ids only for
an Objects on Path group, which is the only kind that reads it.
A pasted solid paint with no swatch link and a tint other than 1 now
keeps that tint when no relinking runs. Saved art carries a tint of 1 on
such a paint.