Commit Graph
365 Commits
Author SHA1 Message Date
BFlat 776e468e89 Merge pull request #6242 from annoybot/fix/pdf-gradient-forms-macos
M4: fix PDF gradient placement in transparency groups
2026-11-10 20:05:34 +07: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
dotCooCoo 8ae9ca2012 SVG export: masks over type keep the full region; live art measured expanded
A mask, inverted mask or knockout group over type now keeps the region
that covers any artwork. Type is measured by its layout or, on a path,
by the path, and a reader that sets live type in its own font can draw
it wider, so a region sized from that box could cut glyphs off.

A live object (blend, envelope, repeat, mesh, placed document,
intertwine) under a mask is measured as the art the writer writes for
it, expanded on its own with the same limits.

The writer keeps its symbol boxes and symbols' art reach in plain
fields instead of cells.
2026-11-09 22:37:17 -08:00
dotCooCoo bd0515ccc8 SVG export: mask and filter regions cover the art they apply to
Opacity masks, inverted and unclipped masks, and knockout groups were
written with mask and filter regions of 200,000 x 200,000 units around
the origin. CairoSVG draws each mask into an image of its region's size
and stops with "out of memory", so a file with any of them did not
open; Firefox drew inverted masks wrong and WebKit drew knockout groups
and inverted masks wrong.

Each region now covers what the masked or knocked-out art paints: its
visual box grown by its raster effects, brush art and members' reach,
the mask art's box, and in a scaled symbol instance its strokes and
effects at their own size. A mask whose art reaches past its object
still comes back whole on import.
2026-11-09 22:16:58 -08: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 ae9ab1bc06 PDF import: DeviceN images of one ink or of process plates keep their inks (#6348)
An image in a DeviceN color space opened as an RGB image, losing its inks.

One of one colorant now opens as a Separation image does since #6347: a
grayscale image of its tints colorized by its ink. One of two to 32
colorants that are all process plates (the ink None may be among them)
opens as a CMYK image, each colorant's tint in its plate, its Decode array
applied (8 or 16 bits a sample). A DeviceN image that mixes a spot ink
with other colorants, such as a duotone, still opens as RGB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 03:09:42 +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
Ahmed Gomaa 323b3385bc Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 22:42:50 +02:00
Ahmed Gomaa 9fda083329 Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 20:49:32 +02:00
jmvergesandClaude Opus 5.5 ca59598cd7 PDF import: Separation images keep their ink (#6314)
An image in a Separation color space opened as an RGB image: its spot ink
was lost (no plate in Separations Preview), and Fill and Recolor Artwork
didn't reach its color.

It now opens as a grayscale image of its tints (white where it lays no
ink, black at 100 %, its Decode array applied; 1 to 16 bits a sample, or
one gray channel from its JPEG, CCITT, JBIG2 or JPEG 2000 decoder),
colorized by its ink at 100 %: the spot swatch, a process plate's CMYK
color, or Registration. Its mask becomes its opacity mask, as a CMYK
image's does. The ink is found by the image's color space among those the
file defines, once per image. The ink None, an ink whose color can't be
told, images inside an alpha soft mask, inline images and DeviceN images
open as before; samples that can't be read open in RGB with a warning, and
the ink gets no swatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 18:39:46 +00:00
Ahmed Gomaa 9ffea06f82 Merge remote-tracking branch 'upstream/main' into fix/pdf-export-mark-text 2026-11-09 19:12:24 +02:00
Ahmed Gomaa f2c4743072 Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 19:12:14 +02:00
Ahmed Gomaa 9b797c06d1 PDF export: letters with marks are written once in the text layer
A mark glyph's vertical translation started a new draw_glyphs batch, so
krilla received the cluster's source range again and mapped its
characters twice. Copying or searching the exported PDF then found
doubled letters for Arabic harakat in any font, and for every dotted
letter in fonts that draw dots as zero-advance mark glyphs (Noto Sans,
Naskh and Kufi Arabic).

Keep compatible glyphs on the same layout line in one batch and carry
their relative vertical placement as per-glyph y_offset; horizontal
placement is unchanged (next_x - x advances). Font, size, linear
transform, line/column, paint run, list marker and hyphen boundaries
still split batches. Krilla keeps owning cluster mappings and
ActualText. No importer change.

Regressions decode the content stream and ToUnicode maps: one batch per
layout line, no duplicated cluster assignment, one ActualText per
multi-glyph cluster, contours within 0.05 pt of outline export; mixed
scripts, vertical columns, path rotations and PDF/X variants covered.
The reader round-trip stays an ignored test until the importer consumes
ActualText (#6165).

Addresses #6309.
2026-11-09 18:13:14 +02:00
Ahmed Gomaa 6e71211a16 PDF import: preserve authored text in ActualText spans
Editable PDF import derived characters from glyph Unicode/CID mappings
even when the enclosing marked-content sequence supplied /ActualText.
A span that paints "xy" but says "AB", followed by "C", imported "xyC".

Track the outermost replacement owner per span (absent, explicitly
empty, consumed), decode it with the existing PDF text-string decoder,
emit it once at the first placeable glyph, and let the remaining glyphs
of the span advance the pen without phantom character slots or
inferred spaces. Authored stretches keep their logical order while
adjacent ordinary text still goes through visual-to-logical
reconstruction. Glyph identity still drives font matching. Depth and
size are bounded; oversized or unbalanced spans fall back to glyph
mappings with a warning.

Outlines mode and PDF export are unchanged. Parity docs updated,
scores unchanged.

Fixes #6165.
2026-11-09 17:43:28 +02:00
jmvergesandClaude Opus 5.5 def928c0dc PDF import: image masks open colorized by the color they are painted in (#6313)
A PDF image mask (`/ImageMask true`) painted in a solid color opened as an
RGB image with the color in its pixels: Fill and Recolor Artwork didn't
reach the color, a spot color lost its ink, and the same mask painted again
in another color took the first one, because the painted image was cached
by the mask alone, and so did an uncolored pattern whose cell draws a mask.

It now opens as a grayscale image of what it paints, colorized by that
color, as the .ai reader opens a 1-bit image mask (#5790). A spot color
keeps its swatch and tint. The page's walk counts paths, not images, so the
ink is found from the color space. Readings of a pattern cell are told
apart by colorized images' colors too. Inside an alpha soft mask, or
painted with a pattern, a mask opens as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 14:43:13 +00:00
Patrick Nadeau 3befda6e12 M4: limit gradient documentation to PDF behavior 2026-11-09 08:45:23 -05:00
Patrick Nadeau 6063e662bc M4: correct PDF gradient progress dates after review 2026-11-09 08:45:23 -05:00
Patrick Nadeau ac674accfd M4: fix PDF gradient placement in transparency groups
Move form transforms into page space so Quartz keeps gradients aligned with their artwork. Add macOS rendering regressions and round-trip coverage for transparency, masks, layers and overprint.

Update the fix for the shared craft-pdf writer and the split exporter modules. Preserve upstream mask, coordinate-limit and layer-box fixes, moving the layer's paper bounds into the form's new space too.

Verified all three Quartz regressions fail on upstream 65adb7b21 and all five gradient-form tests pass with the fix. The new translated-layer regression also fails without moving the layer's paper bounds.

Before the final rebase onto 782f213e4: 463 PDF tests passed (one existing ignored test), workspace fmt, PDF Clippy, wasm, pdf-deps, layers, assets and brands passed. The final rebase reconciles documentation only; the PDF crate is unchanged from that tested revision.

After the final rebase, workspace fmt and Clippy pass. Full cargo xtask ci timed out while compiling workspace tests, so the full test suite and remaining CI stages did not complete. The earlier macOS Clippy blocker has been fixed upstream.
2026-11-09 08:45:23 -05: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
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
dotCooCoo 89b61de7f1 Merge main into fix/ai-os23-3678 2026-11-08 19:39:45 -08:00
dotCooCoo df100e978f Merge main into fix/ai-os23-3678
Only a Stroke Style filter's widths written as one centered array come in as the drawn look. A Stroke Offset stroke and widths written for each side stay live with their profile.
2026-11-08 19:39:44 -08:00
Don Omondi 534c44a871 Merge remote-tracking branch 'upstream/main' into fix/eps-sampled-function-shading
# Conflicts:
#	docs/file-format-parity.md
2026-11-08 22:34:40 -05:00
Don Omondi d15f7fbfba Merge remote-tracking branch 'upstream/main' into feat/ai-import-stacked-fills 2026-11-08 22:02:57 -05:00
dotCooCoo d3a323284c Merge main into fix/ai-os23-2831 2026-11-08 18:52:59 -08:00
Don Omondi 8c8d88e286 Merge remote-tracking branch 'upstream/main' into feat/ai-import-stacked-fills
# Conflicts:
#	crates/eps/src/import/ai/tests.rs
#	docs/file-format-parity.md
2026-11-08 21:08:47 -05:00
dotCooCoo 0fc62c2cf3 Merge main into feat/jxl-import 2026-11-08 18:04:51 -08:00
dotCooCoo aa74ee433c Merge main into feat/jxl-import 2026-11-08 16:52:56 -08:00