Commit Graph
578 Commits
Author SHA1 Message Date
BFlat b34c652a60 Merge pull request #6514 from ruchirguitar/fix/5820-general-units-for-unitless-files
#5820: files that record no units open in Preferences › Units › General
2026-11-11 12:35:44 +07:00
ruchirguitar 52918add2d #5820: keep ruler units the EPS program header gives when the editing data has none 2026-11-11 10:12:00 +05:30
BFlat bc814012d9 Merge pull request #6511 from dotCooCoo/feat/artboard-color-labels
Artboards: an artboard's guide label colors its own guides
2026-11-11 11:27:16 +07:00
ruchirguitar f5daa27a2f #5820: files that record no units open in Preferences › Units › General
A PDF, an EPS or .ai without ruler units, a raster image, a metafile, an
Affinity file or an importer plug-in's document opened (and reverted) in
points whatever the General unit was. They now open in the General unit,
as the reference app opens files that record no unit. Native, SVG and DXF
files and a .ai or EPS with %AI5_RulerUnits keep their own units. Only the
displayed units change, not the art.
2026-11-11 09:56:19 +05:30
dotCooCoo beef32b8a3 Artboards: an artboard's guide label colors its own guides
Each artboard can carry a guide label: one of the layer colors or a
custom RGB. Guides that belong to an artboard draw in its label color,
and guides without an artboard, or on an artboard without a label, keep
the guide color from the preferences. Selected guides still draw in the
selection color.

- Artboard Options has a Guide Label row (None, the layer colors with
  swatches, or Custom with a color swatch).
- artboard.new and artboard.setProps take guideLabel: null, a layer
  color's name, or #rrggbb. Any other value is an error. The inspect
  summary lists guideLabel when one is set.
- The native format saves the label and skips it when unset; a preset
  index outside the layer colors reads as no label.
- artboard.setProps no longer adds an undo step when nothing changes.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-10 19:37:17 -08:00
jmvergesandClaude Opus 5.5 d0c99cba4b .ai import: a warp of type's second try leaves checks for the envelopes after it
A warp of type may now spend up to four checks (its warp and its saved
grid, each with and without strokes). A try after the first is only
made while more checks are left than there are envelopes of type and
warped text objects still to come, so one envelope's retries don't use
up the checks of the others.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:24 +00:00
jmvergesandClaude Opus 5.5 198bb6dffd .ai import: an envelope's grid reads its way round from every row and column
Summing only the end rows and columns let a grid symmetric about its
middle (a mesh bent halfway round) read by rounding, so it came out
turned or not depending on where it sat on the page. Every row and
column is now summed, a sum shorter than 1% of its parts (or than the
grid's reach) counts as no direction and falls back to the first row or
column, and the same comparison decides both cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:24 +00:00
jmvergesandClaude Opus 5.5 37e3c0215a .ai import: type in an envelope may map from its bounds with strokes
With Distort Appearance, an envelope's contents map from the box the
file measured for them: their bounds with their strokes or without
them. For type, the size the file saves for that box is often out of
date, so it can't say which. Envelopes of type are now checked both
ways: as before, and mapping from their bounds with their strokes.
Whichever draws as the drawn art opens live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:13 +00:00
jmvergesandClaude Opus 5.5 7504a0e2e4 .ai import: an envelope mesh bent far round reads the way it runs
An envelope's mesh is turned upright by which way its rows and columns
run. That was read from the first row alone, so a warp bent past halfway
(its end columns leaning more than 45 degrees) read as turned round and
mapped its contents across instead of along. Read it from the first and
last rows and columns added up instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:13 +00:00
jmvergesandClaude Opus 5.5 8f3f6a82d7 .ai import: a warp of type opens as a mesh envelope on its saved grid
A warp of type whose own warp doesn't draw as its drawn art is checked
again as a mesh envelope on the grid the editing data saves for it, its
points and handles as saved. Where that draws as the drawn art, it opens
live in its place: the type stays editable in that shape, and the warp's
style and bend are lost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:13 +00:00
jmvergesandClaude Opus 5.5 83245cfe54 .ai import: stroked type keeps its cap, join and miter limit (#6472)
The text document reader set a type stroke's paint and weight but never
its cap, join or miter limit, so every stroked text object imported from
a .ai or EPS editing copy drew with a miter join at a limit of 10. Type
the file strokes with round joins, or with a miter limit of 4 or less,
drew long spikes at its sharp corners.

Keys 61, 62 and 64 of a run's character attributes (the run, its
character style, then the document defaults) are now read as the
stroke's cap (0 butt, 1 round, 2 projecting), join (0 miter, 1 round,
2 bevel) and miter limit, as PostScript numbers caps and joins. In the
users' files the page strokes type with exactly these settings. Other
values keep the defaults, a miter limit is capped at 500, and type
without a stroke keeps the defaults.

- ate.rs: Style reads the three keys and char_style passes them on,
  with a unit test over defaults, character styles, run overrides,
  hostile values and unstroked type.
- tests_native.rs: an imported story with round, bevel, default and
  unstroked runs.
- docs/file-format-parity.md: revision row, status line, one line on
  the mapping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 02:20:38 +00:00
ruchirguitarandClaude Opus 5.5 163ce1731b G9: .ai font set keys on version too; test /5 (#6388)
Two installed versions of one font are two fonts of the set, so each
keeps its own /5. The generated variable test font now has a version
(name ID 5), and the test checks each variable record writes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 01:30:11 +05:30
ruchirguitar 971800c92c Merge remote-tracking branch 'origin/main' into fix/6388-ai-variable-font-instance
# Conflicts:
#	docs/file-format-parity.md
#	docs/gaps.md
2026-11-11 00:31:15 +05:30
ruchirguitarandClaude Opus 5.5 405062084d G9: .ai save names a variable font instance's design space (#6388)
A variable font's CoolTypeFont record in the text document now carries
/4 (its design vector, one 16.16 value per fvar axis) and /5 (its
version string), and the font set keys on name plus design vector, so a
named instance or a run's own axis setting no longer opens at the
font's default instance. Static fonts are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 00:25:12 +05:30
jmvergesandClaude Opus 5.5 309d7e5363 Envelopes: put back only the outermost drawn art, and keep hidden type until the drawn art is found
The put-back after a failed page check replaces each live envelope with
its drawn art in one go, which fails as a whole when one envelope lies in
another's art: only the outermost are put back now. A live envelope of
type removes its hidden type only once it has found the drawn art it
replaces. The file format docs lose a revision row left twice by a rebase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 17:26:29 +00:00
jmvergesandClaude Opus 5.5 06d0651ebf .ai import: an envelope of type bound to a visibility variable keeps its drawn art
A variable library binds the text object a slot of the envelope's
contents became, which stays hidden beside the drawn art. Once the
envelope opened live that hidden text object went, and its type in the
envelope has an id of its own, so a visibility binding was dropped and
counted as one that wasn't made. A slot bound to a text variable
already kept the drawn art; one bound to a visibility variable does
too now, with the note, so the binding is kept.

Carrying the binding over to the type in the live envelope would bind
an object inside an envelope's contents, which nothing in the import,
the data sets or the .ai writer is known to handle, so it is left for
later.

Part of #3179.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 17:26:19 +00:00
jmvergesandClaude Opus 5.5 bf716bfecc .ai import: envelopes of type keep their drawn art in layers used though they differ from the page
An envelope of type opens live only where the layers with it draw as
the page. Two ways of using layers that don't left it live all the
same: the editing data trusted (they come from it with a note), and
the objects that draw differently coming in as the page's art. In both
the envelope now keeps its drawn art and its type, hidden, with the
note, as where its drawn art is put back. A .ai whose layers would
open alone, without its PDF part, then opens alone again, as it did
before envelopes of type could open live, rather than compared with
the page.

The type put back no longer carries the mark of type made from the
text document in its name.

Part of #3179.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 17:26:19 +00:00
jmvergesandClaude Opus 5.5 0916b40654 .ai import: the page check weighs a live envelope of type as the art it draws
The comparison with the page counts the area of each text object that
shows as type, which it holds to less (type laid out again from the
file's text can sit a little apart from the page's). It took the text
object in a live envelope's contents for such type, at its own unbent
box, so most of what an envelope of type draws went unweighed: one
opened live where the page draws other art there, with only a note
that the type differs. The envelope draws its type bent, as art, and
is now weighed as such, as the drawn art it takes the place of is.

Part of #3179.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 17:26:19 +00:00
jmvergesandClaude Opus 5.5 47b20b4366 .ai import: envelopes of type open live where they draw as their drawn art
An envelope whose contents hold type kept its drawn art, with the type
hidden, because the type is laid out from the text document only after
the layers are read. It now waits for that, as warped type does: once
its text slots hold their type, the envelope is made of that type and
drawn by VectorCraft's own rule, and where it draws as the drawn art the
file saves (the same check and budget as other envelopes) it takes the
drawn art's place, with the type visible and editable in Edit Contents.
The hidden copy of the type goes.

As other live envelopes are, it is held to the page: when the layers
with it don't draw as the page, its drawn art and hidden type are put
back. A .ai whose layers would open alone, without its PDF part, now
waits on the PDF part when an envelope of type is in them; where none
opens live, the layers open alone as before. Layers built without a page
leave envelopes of type their drawn art.

Elsewhere it keeps its drawn art and hidden type, with the note: type in
a font that isn't available, a slot without made type (threaded, bound
to a text variable, a wrap object, type a look draws), an envelope that
doesn't read, no check left, or one that draws differently. Envelopes in
a symbol's or a pattern's art keep their drawn art.

Part of #3179.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 17:26:19 +00:00
jmverges 636c7951f9 Merge main into fix/3179-envelope-type-note
# Conflicts:
#	docs/file-format-parity.md
2026-11-10 11:00:42 +00:00
jmvergesandClaude Opus 5.5 3b1b5c7d47 .ai import: the live envelope and warped type check sees white art (#6412)
The check that keeps a live envelope or warped type only where it draws
as the art saved with it renders each on its own, over nothing, and
compared the pixels as seen on white. White art over nothing looks like
nothing on white, so white contents that drew somewhere else passed and
opened live in the wrong place.

Pixels now also differ when they look different seen on black, so such
art keeps its saved art, as colored art does. Opaque colored art is
compared as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 07:59:02 +00:00
jmvergesandClaude Opus 5.5 b5f62c75b9 .ai import: the envelope type note doesn't promise the type is kept
A text slot the text document gives nothing is left out, with a note of
its own, so the note for type in an envelope no longer says the type is
kept hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 03:15:38 +00:00
jmverges 14b2a60e73 Merge main into fix/3179-envelope-type-note
# Conflicts:
#	docs/file-format-parity.md
2026-11-10 03:15:38 +00:00
jmvergesandClaude Opus 5.5 c67a624128 .ai import: a note for type in an envelope (part of #3179)
An envelope of type keeps its drawn art with its type hidden, but nothing
in the import notes said so, while the other envelopes that keep their
drawn art do. Opening such a file now notes that the type in an envelope
comes in as the envelope's drawn art, not as editable type, and that the
type is kept hidden. The type is still not editable in the envelope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 02:40:38 +00:00
jmvergesandClaude Opus 5.5 0aeb8e8792 .ai import: images in a spot ink's Separation space keep their ink (#6350)
An image whose color space XC sets to one ink (n [c m y k /DeviceCMYK
(name) /Separation] XC) opened as a gray RGB image: its samples, the ink's
tints (255 at 100 %), were read as gray levels, so the tints drew inverted
and the ink was lost.

It now opens as a grayscale image of the tints, black at 100 %, colorized
by the ink at 100 %: its spot swatch, a process plate's CMYK color, or
Registration. Its alpha channel becomes its opacity mask, a reduced large
image's too (a colorized image reduced to fit the limits no longer keeps
its alpha in its pixels). 8-bit and 1-bit samples, binary or in hex
comment lines. A device space and the ink None change nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 02:07:53 +00:00
JonRC d439d734e6 EPS import names the missing fonts of the document's type (#6326 follow-up)
The warning #6326 added listed the families `set_text` met while the
page ran. An Illustrator EPS can be rebuilt from its editing copy,
whose type may be in other fonts than the page's, and `stringwidth` and
`charpath` reach `set_text` without adding any type. The families are
now taken from the text objects of the document the import gives (its
layers and its symbols), once each, in the order the type comes,
whichever path built it.
2026-11-09 14:01:27 -03:00
JonRC ddbc0d545a Fix #6320: EPS import warns about fonts that aren't available
Type set in a family that isn't available keeps its name and shows in
the fallback font, as in PDF import, but EPS import said nothing. It
now notes each such family once, in the order its type comes (at most
64), and ends with PDF import's warning: "fonts that aren't available
show in the fallback font until they are: <families>".

Tests that set type in fonts the test machine may lack (Helvetica,
Ryumin, made-up names) check the program's warnings without that note,
since which fonts are installed depends on the machine.
2026-11-09 12:31:17 -03:00
Don Omondi 9d23da0c41 EPS/.ai editing data: a ligature glyph named by a private-use character matches its text object
When the page's type is matched with the text objects, page words are also
split at private-use characters (from uniXXXX ligature glyph names such as
/uniE028 for a "ti" ligature) and each piece is matched as its own word, so
"Quality" set with that ligature matches its text object and the layers are
read without a false note.
2026-11-09 04:43:53 -05:00
Don Omondi f71c6aaf5b EPS import: CIDFonts only named, over a Unicode CMap, set their characters as live type
A CMap name of the public Unicode CMap form (UniJIS-UCS2-H, UniGB-UTF16-H
and similar) is understood without being defined in the file, so type in a
CIDFont the file only names decodes to its Unicode characters and is set as
live type.
2026-11-09 03:48:35 -05:00
Don Omondi dc00c31a24 EPS import: CMap mappings to base fonts' codes and glyph names draw their glyphs
bfchar and bfrange mappings are kept in the CMap and carried over by
usecmap. A code mapped to a character code draws that code in the base font
usefont named; a code mapped to a glyph name draws that glyph.
2026-11-09 03:48:35 -05:00
Don Omondi 6854529b83 EPS import: CID-keyed fonts in a FontSet's CFF data draw their glyphs
Each CID-keyed font in a FontSet's CFF data is defined as a CIDFont named by
the CFF Name INDEX, with its glyphs found by CID through the charset and
FDSelect, so a composefont over it draws its type.
2026-11-09 03:48:35 -05:00
Don Omondi eb8b8b2850 EPS import: kshow runs its procedure between the characters of live type
Between each two characters the kshow procedure runs with the two codes and
the current point after the first, in any font, not only Type 3 fonts. Where
it moves the current point the next character follows, kept as tracking.
2026-11-09 03:48:35 -05:00
Don Omondi 1b7c648da6 EPS import: embedded Type 1 fonts draw and space their type with their own glyphs
An embedded Type 1 font's eexec part is decrypted and its charstrings read,
so its glyphs and widths are used instead of the installed or fallback
font's. Codes are decoded through the font's Encoding, so fonts that place
glyphs at low codes no longer lose their type.
2026-11-09 03:48:35 -05:00
Don Omondi fde5a5fbef EPS import: CID-keyed fonts draw the glyphs of the CIDFonts the file carries
Adds composefont, the CIDInit and FontSetInit procedure sets and the CMap
operators, so EPS with CID-keyed fonts (as pdftops -level3 writes) opens.
Type 0 fonts with FMapType 9 decode their codes through the CMap's codespace
ranges and CID mappings, and the Identity CMaps are predefined.
2026-11-09 03:48:35 -05:00
Don Omondi 7a25b86a75 EPS import: Type 42 fonts take their characters and widths from the font they carry; show spacing kept as tracking
A plain Type 42 font now maps each code to its character through its glyph
names, or through the glyph its CharStrings give it in the font's own
character map or post names, instead of reading the code as Latin-1. The
font's own widths move the current point, charpath outlines its glyphs, and
the show operators' spacing and the embedded widths are kept on live type as
tracking. Type shown under nulldevice no longer appears.
2026-11-09 03:48:35 -05:00
Don Omondi 1d9833f7de Merge remote-tracking branch 'upstream/main' into fix/eps-memory-cap
# Conflicts:
#	docs/file-format-parity.md
2026-11-09 01:53:05 -05:00
BFlat 977ce06c10 Merge pull request #6018 from mockydevs/fix/eps-sampled-function-shading
EPS import: sampled functions interpolate between their samples (function shadings no longer come in as flat blocks)
2026-11-09 14:45:38 +08:00
Don Omondi 2aa23047fb Merge remote-tracking branch 'upstream/main' into fix/eps-memory-cap
# Conflicts:
#	docs/file-format-parity.md
2026-11-09 00:54:37 -05:00
BFlat fbf43fccf0 Merge pull request #5200 from dotCooCoo/fix/ai-os23-3678
.ai import: objects with a centered variable-width stroke come in as their drawn outline
2026-11-09 13:48:39 +08:00
Don Omondi a27bd53a39 Merge remote-tracking branch 'upstream/main' into fix/eps-sampled-function-shading
# Conflicts:
#	docs/file-format-parity.md
2026-11-09 00:32:17 -05:00
BFlat d90cc305fa Merge pull request #6148 from magyarb/fix/ai-right-aligned-tabs
.ai/EPS import: type keeps its tab stops, and right-aligned lines with tabs lay out as the file's page
2026-11-09 13:18:23 +08:00
Don Omondi 086b67e93f Merge remote-tracking branch 'upstream/main' into fix/eps-sampled-function-shading 2026-11-09 00:01:46 -05:00
dotCooCoo d3d56f01ce Merge main into fix/ai-os23-3678 2026-11-08 20:58:09 -08:00
BFlat baa7248e76 Merge pull request #5158 from dotCooCoo/fix/ai-os23-2831
.ai import: names that aren't UTF-8 can be read in a legacy code page
2026-11-09 12:46:30 +08:00
M Balazs PC 68133cc731 Merge remote-tracking branch 'origin/main' into fix/ai-right-aligned-tabs
# Conflicts:
#	docs/file-format-parity.md
2026-11-09 05:45:48 +01:00
dotCooCoo 09cbf2b8f9 Merge main into fix/ai-os23-3678 2026-11-08 20:24:23 -08:00
Don Omondi 6199fcccf3 Merge remote-tracking branch 'upstream/main' into fix/eps-sampled-function-shading
# Conflicts:
#	docs/file-format-parity.md
2026-11-08 23:15:30 -05:00
BFlat 6ced5794ee Merge pull request #6016 from mockydevs/feat/ai-import-stacked-fills
EPS/.ai editing data: paths keep art styles of several fills and strokes live
2026-11-09 12:13:08 +08:00
M Balazs PC b64cfed610 Merge remote-tracking branch 'origin/main' into fix/ai-right-aligned-tabs
# Conflicts:
#	crates/text/src/layout/flow.rs
#	docs/file-format-parity.md
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-09 04:48:48 +01:00
dotCooCoo 3258785476 Merge main into fix/ai-os23-2831 2026-11-08 19:44:24 -08:00