Commit Graph
767 Commits
Author SHA1 Message Date
BFlat cbba5e85fe Merge pull request #7528 from dotCooCoo/feat/ai-style-named-gradients
PDF/.ai import: graphic styles that paint with a named gradient load with it
2026-11-14 21:54:55 +07:00
BFlat cb99b78a40 Merge pull request #7441 from dotCooCoo/fix/eps-johab-code-space
EPS import: KSC-Johab type reads one-byte ASCII codes
2026-11-14 21:54:39 +07:00
BFlat a15b44fbe4 Merge pull request #7492 from dotCooCoo/fix/eps-bitmap-glyph-rollback-test
EPS: a test covers type taken back with its color bitmap glyph images
2026-11-14 21:51:13 +07:00
BFlat 94237e00a9 Merge pull request #7268 from dotCooCoo/fix/ai-warped-image-pieces-cropped
.ai export: the pieces of a warped image write only the pixels they show
2026-11-14 20:38:46 +07:00
BFlat 31f6a9f15e Merge pull request #7367 from dotCooCoo/fix/ai-calligraphic-samples
.ai import: Calligraphic paths with pen samples keep their drawn look
2026-11-14 20:38:22 +07:00
BFlat ca0050be1b Merge pull request #7578 from dotCooCoo/fix/gradient-spot-colorants-drawn-stops
PDF and EPS export: gradients name only the spot inks of stops that color something
2026-11-14 20:37:42 +07:00
dotCooCoo efb31aa51a PDF and EPS export: gradients name only the spot inks of stops that color something
A gradient's Separation or DeviceN space, and EPS's %%DocumentCustomColors,
named the spot ink of every linked stop. A stop out of order whose
neighboring stretches have no width, a stop at a tint of 0 without process
plates, and in PDF a stop whose stretches are fully transparent print no
ink, but their spot inks were still declared, so separations got an empty
plate.

- vectorcraft-color: Gradient::drawn_stops (the rule Document Info uses,
  moved here) and Gradient::reached_stops (every stop taken as opaque).
- PDF: Separation and DeviceN shadings, the Perceptual spot shadings and
  the spot-image warning name only inks of drawn stops at a tint above 0
  or with process plates; other stops are written with no ink, so their
  process inks and RGB or Lab colors no longer shape the space either.
- EPS: the same with reached stops, since EPS writes stops opaque; a
  transparent spot stop keeps its ink.

Output is unchanged when every stop colors part of the gradient and every
spot stop has a tint above 0 or process plates.
2026-11-14 04:11:40 -08:00
dotCooCoo 0397bfa47f Merge main into fix/ai-calligraphic-samples 2026-11-14 02:53:05 -08:00
dotCooCoo 110cf34f29 Merge main into feat/ai-import-kinsoku-settings 2026-11-14 02:32:17 -08:00
dotCooCoo 9965454983 Merge main into fix/eps-bitmap-glyph-rollback-test 2026-11-14 02:17:57 -08:00
dotCooCoo f21c9561c5 Merge main into fix/ai-warped-image-pieces-cropped 2026-11-14 02:14:20 -08:00
dotCooCoo cbbed9fa6c Merge main into fix/eps-johab-code-space 2026-11-14 02:08:25 -08:00
dotCooCoo cdd6ffa1f2 PDF/.ai import: graphic styles that paint with a named gradient load with it
A graphic style from a .ai or EPS library whose fill, or the fill or
stroke of a style of one paint, paints with one of the file's gradients
by name was left out of the library. Such styles now load with that
gradient at the style's angle. The style stores only the gradient's name
and angle, so the gradient is fitted to the bounds of each object the
style is applied to; this placement is VectorCraft's own rule.

- A style of one paint reads a gradient instance's fill or stroke as
  that gradient; a gradient outside an instance is still not read.
- A fill filter paints with its last paint: a color, a gradient or a
  pattern replaces whichever of the others came before it.
- A style naming a gradient the file doesn't define, or painting with a
  pattern, is still left out.

Docs: docs/mcp.md, graphicStyle.loadLibrary params, progress doc.
2026-11-14 02:05:00 -08:00
dotCooCoo 7517ef0db3 Merge main into fix/ai-warped-image-pieces-cropped 2026-11-14 01:54:59 -08:00
BFlat 111ceddb9b Merge pull request #7383 from dotCooCoo/feat/ai-art-brush-options
.ai import and save: Art brushes keep None, their width, scale and flips
2026-11-14 16:54:16 +07:00
BFlat 158e7eed5c Merge pull request #7500 from dotCooCoo/fix/eps-freeform-field-once
EPS: a freeform gradient's image drawn more than once writes its samples once
2026-11-14 16:52:10 +07:00
dotCooCoo 9feda4f5a6 Merge main into fix/eps-johab-code-space 2026-11-13 23:01:15 -08:00
dotCooCoo 780fbee2eb Merge main into feat/ai-import-kinsoku-settings 2026-11-13 22:58:23 -08:00
BFlat 05409f76f5 Merge pull request #7394 from dotCooCoo/fix/ai-linked-image-warp
.ai save: a linked image with a Warp keeps its live Warp and its link
2026-11-14 13:44:00 +07:00
BFlat ab959b95a8 Merge pull request #7369 from dotCooCoo/fix/ai-hidden-ruler-guide
.ai import: hidden ruler guides open as ruler guides with their own state
2026-11-14 13:43:11 +07:00
BFlat 0ca2952093 Merge pull request #7363 from dotCooCoo/fix/stained-instance-export
Symbols: a stained instance keeps its stain in SVG, PDF and the other exports
2026-11-14 13:42:39 +07:00
dotCooCoo fc14b8a78f EPS: a freeform gradient's image drawn more than once writes its samples once
A freeform gradient's image was sampled, encoded and written inline at
every fill, outside the reuse placed images have. Fields now go through
the same codes and placements: a fill whose encoded image (color setup,
image dictionary, filter, operator and samples) matches one already
kept draws from it, so its samples are written once in the setup as
VCim<i>. A field drawn once is still written where it is drawn.

A fill whose placement can't be drawn, or that arrives when the page is
already at the 256 MB limit, is no longer sampled first, and a field
image taken back with art that passed the limit is forgotten.
2026-11-13 22:34:26 -08:00
dotCooCoo bb81d0d8b3 Merge main into feat/ai-art-brush-options 2026-11-13 22:33:50 -08:00
dotCooCoo a5a67f8c4d EPS: a test covers type taken back with its color bitmap glyph images
Type whose color bitmap glyphs fit under the page limit, but whose run
fill passes it, is left out together with the image placements of its
glyphs. The new test builds the color font in memory and checks that
the page then equals the page without that type: no reference or shared
resource is left for the glyph image, a glyph drawn once elsewhere is
written inline again, and an image drawn twice keeps its shared samples.
2026-11-13 22:18:45 -08:00
dotCooCoo 774ffbbc21 EPS import: KSC-Johab type reads one-byte ASCII codes
The KSC-Johab CMaps had no code space listed, so type in a font over
KSC-Johab-H or KSC-Johab-V read every code as two bytes, so two ASCII
characters moved the point one em instead of two. The code
space now follows Adobe's KSC-Johab-H CMap: <00>-<80>, <8441>-<D3FE>,
<D831>-<DEFE> and <E031>-<F9FE>
(https://github.com/adobe-type-tools/cmap-resources/blob/master/Adobe-Korea1-2/CMap/KSC-Johab-H).
2026-11-13 20:47:32 -08:00
dotCooCoo 702b863306 .ai import: reads Kinsoku, Kinsoku Shori Type, Burasagari and Bunri-Kinshi
Paragraphs in a modern .ai text document now keep their East Asian line
breaking settings: the Kinsoku set (None, Hard or Soft), Kinsoku Shori
Type, Burasagari and Bunri-Kinshi. Each comes from the paragraph, else
its paragraph style or a style that one is based on, else the document's
defaults, as the other paragraph settings do. A value that cannot be read
takes the paragraph style's value.

A paragraph whose Kinsoku set is a custom set takes its paragraph
style's set, and the import warns that custom Kinsoku sets were left out.
.ai export does not write these settings.
2026-11-13 20:36:17 -08:00
dotCooCoo 0a68935bf2 .ai import: Art brush guides match as fractions of the art too
A path's guide lengths matched the brush's within 0.001, so on very short art guides at 30% and 35% of the art matched. The guides now also match as fractions of the art's length.
2026-11-13 20:35:50 -08:00
dotCooCoo 991c36458a .ai import: an Art brushed path opens live only when its own settings would
A path's Art brush settings matched the brush's within a small tolerance, and only the brush's were checked. A path with a Spacing of 0.0005, or guides that leave no art between them, opened live with the brush's settings. The path's settings now pass the same checks as the brush's, and such a path keeps its drawn look.
2026-11-13 20:03:35 -08:00
dotCooCoo e9ae8b9661 Merge main into fix/ai-calligraphic-samples 2026-11-13 19:50:31 -08:00
dotCooCoo 7602a7a57a Merge main into fix/ai-warped-image-pieces-cropped
# Conflicts:
#	crates/eps/src/ai_editing/writer.rs
2026-11-13 19:31:11 -08:00
dotCooCoo 94db0b1ebd .ai export: a masked image copy whose mask is left out keeps all of its pixels
A copy of an image written whole already was cut to the painted bounds of
its opacity mask even when the mask was then left out, nested too deep or
past the object limit, so the file read back with a cropped image and no
mask. The copy is now cut to its mask only when the mask is written, and
otherwise written whole.

The progress-doc line now gives the measured total for the warped test
image's pieces: about 7 times the image's samples, not twice.
2026-11-13 19:20:35 -08:00
Dylan M. Taylor 1e4e3534f5 Merge pull request #7398 from storytold/feat/craft-libs-migration
Migrate CAD (DXF), EPS/PostScript, and SVG to craft-libs (#778)
2026-11-13 22:14:10 -05:00
dotCooCoo 49a3c3d718 Merge main into feat/ai-art-brush-options 2026-11-13 19:09:26 -08:00
dotCooCoo 87c8def043 .ai save: a linked image with a Warp keeps its live Warp and its link
A linked image whose appearance is one Warp effect, with no opacity mask,
was saved to the .ai editing data as its drawn art, so its live Warp was
lost. It is now written with an art style of that Warp, as an embedded
image is: its bent pieces are its drawn look, and the image itself
follows on %_ lines as a placed file with its path, its folder relative
to the document's and its preview. In an opacity mask's art the copy is
embedded, with the existing warning for linked images in masks.

Opening such a file reads the image back linked, with its Warp live.
A hidden image with a Warp, embedded or linked, is now compared with its
drawn look shown, so it keeps its Warp too; before, the look drew
nothing and the image came in as its drawn pieces.
2026-11-13 18:51:03 -08:00
BFlat ea24f694cf Merge pull request #7345 from dotCooCoo/fix/ai-twist-straight-guide-reach
.ai import: straight compound paths whose guides reach past them keep the drawn look under Twist
2026-11-14 09:32:51 +07:00
dotCooCoo 719e3450b2 .ai import and save: Art brushes keep None, their width, scale and flips
A .ai path with an Art brush opened with the brush on its stroke only
when the brush stretched its art at 100% in Tints, unflipped. Paths with
an Art brush in None, at another fixed width, with Stretch Between
Guides, or flipped along or across now open as the path with the brush
on its stroke too, and the brush in the Brushes panel has those options.
The guides come in as fractions of the art, from the lengths of the art
outside them. A brush with Scale Proportionately comes into the panel
with that option, and its paths keep their drawn look.

Paths keep their drawn look when their settings that change the drawing
differ from the brush's, and when the brush is in Tints and Shades or
Hue Shift, has a width that follows the pen, has guides that leave no
art between them, or has a Spacing, Adjustment or FoldAdjustment other
than 0, 1 and 1.

The .ai save writes the same options, so such brushes and the paths
that use them come back as they were; a path with a proportional brush
is written as its brush's art.
2026-11-13 18:27:54 -08:00
dotCooCoo 7b475b46b0 .ai import: Calligraphic paths with pen samples keep their drawn look
A path's own lines can be followed by samples of the pen
(`(…) Xt n XD`). The reader took them as the end of the object, so the
style marker after them was not matched: the path came in as its drawn
look plus a second, unpainted copy of the path, and no note said the
look was kept. The samples now stay with the path. They aren't read,
so a path that has them keeps its drawn look alone, with the note, when
a setting of its Calligraphic brush varies with the pen (Pressure,
Tilt, Bearing or Rotation, with a variation above 0). With any other
style, an Art brush or a Calligraphic brush that doesn't follow the
pen included, it takes the style as it would without them.

A Calligraphic brush's filter with an entry the reader doesn't know, or
with a variable width, keeps the drawn look too, as an Art brush's
filter does.

Docs: docs/file-format-parity.md, docs/gaps.md.
2026-11-13 17:59:50 -08:00
dotCooCoo 1e4b6c4e22 Merge main into fix/ai-hidden-ruler-guide 2026-11-13 17:56:13 -08:00
dotCooCoo cfa76d674f .ai import: hidden ruler guides open as ruler guides with their own state
A straight `(N) *` guide path that runs across the canvas or an artboard
opens as a ruler guide, but a hidden one (`1 Xw`) stayed a guide path.
It now opens as a ruler guide too, and every ruler guide made from such a
path keeps the path's hide, lock and name, so its Layers row shows them.
Before, a locked guide opened unlocked and a named one lost its name.

Hidden or locked guide paths that are short, slanted, grouped or `(S) *`
stay guide paths, and commented copies (`%_`) are still left out.

Docs: docs/target-app-parity.md, docs/file-format-parity.md.
2026-11-13 17:55:31 -08:00
Dylan M. Taylor e927729f25 SVG: delegate entity expansion bounds, sniffing, and SVGZ to craft-svg 2026-11-14 01:40:55 +00:00
BFlat bf3cf422e2 Merge pull request #7311 from dotCooCoo/fix/ai-graphs-keep-data
PDF/.ai import: graphs keep their data and settings when their records read whole
2026-11-14 08:39:57 +07:00
Dylan M. Taylor cb5b06672f EPS: delegate binary preview header, sections, and ASCII85 to craft-eps 2026-11-14 01:28:35 +00:00
dotCooCoo de8ac51502 Symbols: a stained instance keeps its stain in SVG, PDF and the other exports
A symbol instance colored with the Symbol Stainer lost its stain in
export whenever the canvas's stained art was not used:

- An instance with geometry effects was reshaped for export from the
  symbol's art with only its dynamic changes, so SVG, PDF, EPS, .ai,
  DXF, EMF/WMF and HPGL wrote the unstained colors. A color adjustment
  on an instance recolored the unstained art the same way.
- PDF, EPS, legacy .ai, DXF and EMF/WMF wrote an instance without
  effects from the unstained art.

tint_node, stain and instance_art now live in
vectorcraft_doc::symbol_overrides, which both the effects and the
exporters can use; vectorcraft_brush re-exports them. Baking, color
adjustments and the writers above now use instance_art: dynamic changes
first, then the stain.
2026-11-13 17:24:06 -08:00
dotCooCoo be8d614b0c .ai import: straight compound paths whose guides reach past them keep the drawn look under Twist
A straight compound path with Twist was read live up to 180° whatever
guides it held, and the live Twist was measured from bounds that take in
the guide members. A straight compound path with Twist whose guide
members reach past its other members now opens as its drawn look
instead of live, and so does a compound path made only of guides.
Compound paths whose guides lie inside their other members, a Twist of
0°, and single paths keep opening live.

The `.ai` writer keeps a graphic-style link only where the reader reads
the style live, so such an object is now written without the link, with
the existing style-link warning.
2026-11-13 16:35:37 -08:00
BFlat f14aa09bbf Merge pull request #7226 from dotCooCoo/fix/legacy-ai-type-kerning
PDF/.ai import: legacy type keeps manual kerning, discretionary hyphens and language
2026-11-14 07:34:10 +07:00
dotCooCoo b097c2a957 .ai export: the masked pieces of a warped image no longer hide one another
A raster mesh warp with Preserve Shape Using Transparency cuts an image
into pieces with opacity masks and puts them in a knockout group, each
piece knocking out its triangle. The reader gives the pieces no such
mark, so each knocked out all that its image paints without its mask,
and the file opened with most of the image hidden.

The group of such pieces is now written without knockout. An image
whose pixels are partly transparent draws its alpha twice only where
neighboring pieces overlap.
2026-11-13 16:30:17 -08:00
dotCooCoo 76d99d6afb Merge main into fix/ai-graphs-keep-data 2026-11-13 15:46:07 -08:00
dotCooCoo 492b76ace3 Merge main into fix/ai-warped-image-pieces-cropped 2026-11-13 15:15:36 -08:00
dotCooCoo 11ecbe4e9a Merge main into fix/legacy-ai-type-kerning 2026-11-13 15:00:02 -08:00
dotCooCoo aa5d142bd8 .ai save: the editing copy keeps text wrap Offset and Invert Wrap
A PDF-compatible .ai saved with Include Editing Data for Other Apps
wrote no text wrap options, so a wrap object opened from the file no
longer wrapped type. An object with only wrap options got no
dictionary at all.

The writer now writes each wrap object's options in its dictionary as
`AI11TextWrapOffset` (`/Real`) and `AI11TextWrapInvert` (`/Bool`, 1 or
0), the entries `text_wrap` in crates/eps/src/import/ai/read/document.rs
reads, beside the object's name, variables and opacity mask.

- The offset is the one in the art's space, so on a large canvas it is
  written at 1/10 and read back at its size. An offset that is not
  finite is written as the default 6 pt, and one past the -1000 to
  1000 pt the reader keeps as the nearer end of that range.
- Art the writer draws for an object (a blend's steps, a symbol
  instance written as its art, a brushed stroke's pieces, pattern
  tiles, an object's drawn look) is written without the options of the
  objects it is made from. The object itself and a symbol's own art
  keep theirs.
- A clipping path written as its fills and its strokes has its options
  once.

Docs: docs/file-format-parity.md, docs/target-app-parity.md.
2026-11-13 14:48:16 -08:00