PDF export without a PDF/X or PDF/A standard writes pages longer than
200 in at full size in points instead of with a UserUnit scale.
longPagesInPoints is now on by default in PdfSettings, the built-in
presets and the Save PDF dialog. Turning it off writes such a page with a
UserUnit from PDF 1.6 on, as before. PDF/A-2b files keep the UserUnit,
and .ai saves keep it unless longPagesInPoints: true is passed.
Docs: params text, docs/mcp.md, docs/target-app-parity.md.
Three repairs in crates/pathops/src/addons/cleanup.rs grew with the square
of the input. Each now gives the same results as before, bit for bit.
- Collinear anchors: removing an anchor called Vec::remove, so a straight
run of n anchors took O(n^2) moves. The repair now tests each anchor once
against the nearest kept neighbors, with the same test order, neighbors
and stop rule, and moves the kept anchors into place once.
- Nearly Coincident Anchors (near_point_groups): every pair of anchors in
touching grid cells was compared, so a cluster of A anchors cost O(A^2)
checks. Groups now grow one anchor at a time and look only at anchors no
group has taken, by exact position, skipping quarter-cell squares that
lie out of reach.
- Rejoin Path Pieces (rejoin): every pair of ends within the gap was listed
and sorted, O(P^2 log P) for P pieces meeting at one place. Each end now
finds its first partner in the same order (turn, distance, then end
order), searching by direction among the ends still free, and two ends
that are each other's first partner meet.
Tests compare each repair with a copy of the old algorithm on generated
and focused inputs, count the work on dense cases (20,000-anchor runs,
4,000-anchor clusters, 2,000 pieces meeting at one point), and check Health
Check, Show and Fix on a 5,001-anchor path.
The profiles Edit > Assign Profile gives a document stayed the active
color settings after another document came to the front, so a new,
opened or switched-to document drew and converted its colors through the
previous document's profile, and closing the last document left it in
use.
The session now puts the front document's profiles in use (the working
spaces where it has none, or no document is open) after a new or opened
document, a tab switch, a close, File > Revert, every command including
each batch step and Undo or Redo of Assign Profile, a failed batch or
plug-in call, a script's rollback and slice boundaries, a canceled
preview, undo group or undo scope, and for each document Export All Open
and the update of placed documents work in. The active settings are
rebuilt, and the documents redrawn, only when they change.
document.export and document.serialize to .ai with useArtboards: false
wrote the one page of the visible art, but embedded the one-artboard
stand-in as the native document and as the editing copy for other apps.
Reopened, the file replaced the document's artboards with one artboard
around the art.
- The .ai of the art's bounds now leaves out both editing copies and
returns the warning "Preserve editing was left out: an .ai file of the
art's bounds would replace the document's artboards when reopened",
as the PDF of the art's bounds does.
- useArtboards: false with pdfCompatible: false is refused, with or
without editingData, since the file would have blank pages and no
editing copy.
- Save, Save As, Save a Copy and exports of the artboards keep both
copies. Legacy version 7 .ai files are written as before.
Docs: docs/mcp.md, docs/target-app-parity.md, document.export params.
Join removed each merged anchor from the path's anchor list as it went,
which moved every anchor after it, so a long selected run in front of
many other anchors took time quadratic in the path's length. It also
looked up each anchor's selection in the selected-anchor set.
Join now marks the merged anchors and removes them in one pass at the
end, reading the selection from one flag per anchor. Each corner or
smooth conversion sees the same neighbors as before, so the resulting
anchors are unchanged. Anchor::smooth_between holds the smoothing that
SubPath::smooth_anchor applies.
Tests compare the new merge bit for bit with the old one on 30,000
generated paths, and count the anchors moved when 300,000 selected
anchors in front of 300,000 others merge: each of the others moves
once.
Open and Place store some images again instead of keeping their bytes:
a photo turned by its orientation, a TIFF the image decoder reads, and
a CMYK TIFF with one plane per ink. Those images lost the ICC profile
their file embeds, and 16-bit samples were cut to 8 bits.
- raster_image keeps gray and RGB samples at 8 or 16 bits in the
stored PNG, with the gray or RGB profile in its iCCP chunk. A
profile of another color space, such as the CMYK profile of a CMYK
image read as RGB, is left out. A TIFF's profile is read with the
tiff decoder, which reads it whatever the image's size.
- stored_cmyk_tiff and turned_cmyk write CMYK8 or CMYK16 as the file
has it, with the CMYK profile as TIFF tag 34675 (UNDEFINED). A CMYK
JPEG's profile is put together from all its APP2 segments.
- The docs/target-app-parity.md line on EXIF orientation says 8 or 16
bits, and a line after it describes the kept profile.
A trace made away from its command (the background trace, #3098) counted
as current when the object, its image record and the settings were
unchanged, without looking at the image data. When other pixels came to
sit under the same image key (Rasterize after an undo reuses the key and
the id, Update Link, a replaced blob), the finished trace applied its old
paths to the new image.
The trace's inputs now include the encoded bytes it decodes, compared by
allocation first and then by content. TraceRun::current and the hand-off
in imageTrace.make and imageTrace.makeAndExpand both use them, so a stale
trace is dropped and the command traces the pixels there now. Equal bytes
in another allocation still count as the same image.
Clear, path.deleteAnchors, Cut, Copy and Cut Path scanned every selected
anchor or segment of a path once for each of its subpaths, so a path with
thousands of subpaths took time that grew with the square of their count.
The selection sets are ordered by subpath, so a new helper, subpath_refs,
reads one subpath's entries with a range lookup instead. The results are
unchanged.
With one selected interior anchor on each of 8,000 open subpaths of one
path, Clear took a median of 74 ms of thread CPU time before and 3 ms
after (release build, five runs each; the timings are noisy because the
CPU was shared and loaded).
Tests in delete_path_pieces.rs check exact surviving subpaths and their
order for anchor and segment selections across open and closed subpaths,
an untouched subpath, references to missing subpaths and indexes, one
Undo/Redo step and a second Clear, and Cut Path on several subpaths.
Without a plug-in store, plugin.install read the process grant once
for its later check and again for its approval. A grant another session
recorded between the two reads approved the module; when that session
revoked it before the install, the check saw the grant it first read
and the install recorded the revoked grant again. The approval now comes
from the first read.
plugin.install published the plug-in before it wrote the module and its
grant to the Plug-ins folder. A plugin.remove in another session in
between removed the plug-in, its file and its grant, and the install then
wrote both back, so the plug-in loaded with its grant at the next launch.
A session attaching the folder in between loaded the old version, which
kept running while the folder held the new one. plugin.remove, loads of
the stored plug-ins and loads of a plug-ins folder now wait until an
install has written the folder, and an install waits for them.
Docs: docs/plugins.md, docs/target-app-parity.md.
Object > Path > Remove Anchor Points removed each selected anchor with
its own Vec::remove, shifting the rest of the subpath every time, so
removing k anchors from an n-anchor subpath took O(k*n) moves.
- pathops: remove_anchors removes a subpath's anchors the last first,
reading each anchor's current neighbors, handles, length and closed
state as removing them one at a time does, and compacts the anchor
list once. remove_anchor and remove_anchors share one refit, so the
result is bit for bit the same.
- engine: the command groups the selected anchors by subpath, works out
the next selected anchor with each subpath reading only its own
selected anchors, and takes emptied paths out of the selection
together (Selection::remove_all).
- Tests compare remove_anchors bit for bit with remove_anchor over 600
generated subpaths and focused cases, count the anchors moved (2001
anchors, every other one removed: at most one move per anchor left,
500,500 one at a time), and compare the next-anchor selection and
the command on many paths and subpaths with removing one at a time.
An <image> whose EXIF orientation or TIFF Orientation tag turns or flips
its pixels, linked or as a data URL, is turned before usvg reads it: the
pixels are stored as they are shown, the width and height swap, and the
box fits the turned image under preserveAspectRatio, as CSS
image-orientation: from-image describes. A turned CMYK JPEG or TIFF keeps
its inks as a CMYK TIFF, as does a CMYK TIFF that is not turned.
- Data URLs of type image/tiff, and untyped TIFF bytes, are read.
- TIFFs with extra channels, CCITT Group 3 TIFFs and planar CMYK TIFFs
are read as Open and Place read them.
- Converted images decode within the decode allowance, and a TIFF that
claims more strips or tiles than the decoder can count is refused
before any decoder opens it.
- exif_orientation moves to vectorcraft-doc so Open/Place and SVG import
share it.
Tests: crates/svg/tests/it/image_orientation.rs.
Font Details, Linked Images and Embedded Images, and the Objects counts
Compound Paths, Text Objects, Placed Documents, Symbol Instances, Gradient
Meshes, Blends, Envelopes, Intertwine Groups, Opacity Masks and Objects
with Effects had no catalog rows, so the panel and its category menu
showed them in English in every other language. Each complete catalog
now has them, and the Document rows Pattern Swatches (de, it, ja, ko,
pl, uk, vi, zh-hant) and Path Length (bg, el) are added where missing.
The catalog test now checks every category title, every Objects count
label and Document's fixed row labels. document.info and the saved
report keep the English labels.
The Live Paint Bucket drew the crosshair in place of its own cursor. It
now shows what a click paints: a filled paint bucket over a face it
fills (of a Live Paint group, or a region of the selected paths), a
brush over an edge it paints, and an empty bucket where it paints
nothing. The cursor follows Paint Fills, Paint Strokes and Shift, and
shows with Highlight off too. Alt still shows the Eyedropper, and Use
Precise Cursors shows the crosshair.
With a Live Paint group and ordinary paths selected, a region of the
paths outside the group is now highlighted, as a click there fills it.
The help page: https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html