Commit Graph
831 Commits
Author SHA1 Message Date
dotCooCoo 2992ec6aa0 Merge main into fix/followup-7319 2026-11-14 02:51:49 -08:00
dotCooCoo b59ec11b32 Export: symbol art placement skips instances the export leaves out
Hidden instances, instances in hidden groups, on template layers, and
on hidden layers or layers that do not print when the exporter leaves
those out are no longer placed for PDF, print, EPS and DXF. Their art
was baked and counted toward the 16,000,000-object limit for placed
symbol art, so it could leave a visible instance written without its
effects.

bake_document_placing_symbols takes a WrittenLayers value: PDF passes
the layers its settings write, EPS writes layers that do not print but
not hidden ones, and DXF writes both. Print removes the layers that do
not print before baking.
2026-11-14 02:45:49 -08:00
dotCooCoo 3824b15a77 .ai and EPS import: large canvas symbols come in at the file's size
VectorCraft reads the symbol definitions of a large canvas .ai or EPS,
and of a .ai whose page is in larger units, in the same units as its
layers. Opening such a file scaled the layers and graphic styles up to
full size but left the symbols' art as it was. Instances on the layers
drew at the right size, but each one's transform carried the factor N,
and a newly placed instance came in at 1/N of the size, where N is the
file's large canvas scale or its page's unit.

- Opening the file now scales each symbol's art, strokes and effects with
  the layers. Instances on the layers, in symbol art, in pattern tiles
  and in opacity masks keep their own scale and rotation and draw where
  they did.
- A symbol library without layers from such a file gets the same scale
  as its graphic styles.
- Opacity masks on the layers that do not move with their object are
  scaled with the layers too, as are those in symbol art.
- Editing data that VectorCraft wrote (its %%Creator line) keeps its
  symbols and those masks at their own size, as the .ai save writes
  them, so files saved by earlier versions open as before.
2026-11-14 02:43:50 -08:00
dotCooCoo 1780584f8a Merge main into fix/ai-wrap-options-edge-cases 2026-11-14 02:41:43 -08:00
dotCooCoo 5c4f96fc96 Merge main into fix/eps-cshow-composite-codes 2026-11-14 02:35:54 -08:00
dotCooCoo 6eb0769dfe Merge main into feat/ai-insert-aki 2026-11-14 02:33:44 -08:00
dotCooCoo 110cf34f29 Merge main into feat/ai-import-kinsoku-settings 2026-11-14 02:32:17 -08:00
dotCooCoo ad628c0f3e Merge main into fix/ai-envelope-budget-warped-type 2026-11-14 02:21:54 -08:00
dotCooCoo 4678bda849 Merge main into fix/eps-ryumin-light-h 2026-11-14 02:18:10 -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 df3d012e1f Merge main into fix/export-bakes-symbol-art-effects 2026-11-14 02:07:20 -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 c786f75349 Merge main into fix/ai-envelope-budget-warped-type 2026-11-14 01:56:13 -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
dotCooCoo 79e719dcdd Merge main into fix/export-bakes-symbol-art-effects 2026-11-14 01:53:06 -08: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 653e1fdf22 Merge main into feat/ai-insert-aki 2026-11-13 23:18:06 -08:00
dotCooCoo 66535b725b Merge main into fix/eps-ryumin-light-h 2026-11-13 23:05:31 -08:00
dotCooCoo 05c652f9fc Merge main into fix/export-bakes-symbol-art-effects 2026-11-13 23:04:23 -08: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
dotCooCoo 4aba706e1a Merge main into fix/export-bakes-symbol-art-effects 2026-11-13 22:43:58 -08: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 a98b800761 Export: live effects in symbol art apply in PDF, EPS, print and DXF
PDF, print, EPS and DXF wrote a symbol instance by placing its symbol's
art as stored, so live effects inside that art were missing: a square
moved 100 pt by a Transform effect stayed in place in the file while the
canvas drew it moved.

bake_document_placing_symbols replaces each instance of a symbol whose
art (or the art of a symbol nested in it) needs baking by that art
placed as the instance places it, then baked. The art is placed before
its effects apply, as on the canvas, so an instance that scales its art
does not scale what its effects do. A dynamic instance's own paint
changes apply before baking. Nesting stops at 32 levels and the placed
art at 16,000,000 objects per export; past them an instance stays an
instance. DXF places 9-slice cells unclipped, as its scene does. The
symbols' own art, SVG and the .ai editing data are unchanged, and HPGL
already baked each placed instance.
2026-11-13 22:31:48 -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 e47975d302 Type: .ai import reads Insert Aki, and .ai save writes it
Opening an .ai file now reads Insert Aki Left and Right from its text
document through the same cascade as the other character keys: the run,
its character style and the styles that one is based on, [Normal
Character Style], then the document's defaults. The values are read in
thousandths of an em. A negative value or one that is not a number opens
as 0, and a value past 1000 opens as 1000. How the text document stores
these values is VectorCraft's own rule.

An .ai save writes each run's nonzero values in the form that reader
reads, and no longer reports Insert Aki as left out of the editing data.

A legacy .ai text object has no Insert Aki: type with it that is written
as text now reports that the setting is left out. Type written as
outlines keeps the space.
2026-11-13 21:38:33 -08:00
dotCooCoo ed0a4e0abe .ai save: a clipping path cut away outside keeps its text wrap options
A clipping path inside art cut to another clipping object is written as
its fills and its strokes. Its text wrap options went with the fills, so
when the outer region left nothing of the fills, the strokes were written
without them. The strokes now keep them unless a fill object was written.

A symbol definition that had no room left for its group under the object
limit returned without restoring the writer's drawn-art depth. Asked for
from art drawn for an object (a stained instance's art), the depth then
dropped below zero on the way out, which panics in debug builds. That
path now restores it as the others do.
2026-11-13 21:30:13 -08:00
dotCooCoo c567ecc264 .ai save: text wrap fixes for cut-away clipping fills and symbols without room
Two faults in the editing data writer's text wrap handling:

- A clipping path inside art cut to an outer clipping object is written
  as its fill and its stroke. The stroke's text wrap options were
  dropped whenever the path had a fill, so when the outer object cut
  the fill away entirely, the stroke was written without them and the
  options were lost. The stroke now drops them only after the fill
  writes an object.
- When a symbol definition had no room left under the object limit,
  `define_symbol` returned without restoring the drawn-art counter it
  had cleared. A live instance inside drawn art (a stained instance's
  art) then left the counter at zero, and the art around it subtracted
  from zero: a panic in a debug build. That path now restores the
  counter as the other exits do.
2026-11-13 21:22:19 -08:00
dotCooCoo 597413f113 EPS import: cshow runs once for each character of a composite font
In a composite font the file carries (FMapType 2 or a CMap), cshow ran
its procedure once for each byte of the string, with that byte's width
in the composite font and the composite font still current. It now runs
once for each character the font maps, with the last byte of its code
and its width, and with the descendant that draws it current, at the
size the composite font sets it, while rootfont gives the composite
font (PLRM 3rd ed., cshow and rootfont).

While the procedure runs, showing the byte it was given in that
descendant shows the character the code maps to: a CMap's CID,
base-font code or glyph name. In a CIDFont any other string is a
rangecheck error.
2026-11-13 21:14:37 -08:00
dotCooCoo edee68e3d1 EPS import: Ryumin-Light-H and GothicBBB-Medium-V read as Japanese type without their CIDFont
A name ending in the row-and-cell CMap H or V split only when the file
defined the CIDFont or a face of that name was installed, so
/Ryumin-Light-H findfont in a file that only names it read its strings
byte by byte as a plain font: <467c> came in as "F|" instead of 日.
Ryumin-Light and GothicBBB-Medium, the Japanese CIDFonts a printer
carries (Adobe Technical Note #5014, appendix A.2), now split at H or V
as well. Latin names such as Foo-Bold-H still stay whole.
2026-11-13 20:48:18 -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 5375b6e446 .ai save: images with a Warp count against the envelope limit
Opening an .ai file compares at most 256 envelopes and embedded images
with a Warp with their drawn art, from one budget. Saving the editing
data counted only envelopes, so a file with more than 256 of them in all
was saved with images past the budget written live and no warning, and
it opened with those images as their drawn look.

- The writer's budget now counts every image written with its Warp as
  well as every envelope, in the order they are written. An image past
  it is saved as its drawn look with a warning, and an envelope past it
  as its distorted art, as before.
- An image whose pixels can't be read is written as its gray outline,
  which the reader does not check, so it takes no part of the budget
  and keeps the warning about its pixels.
- The envelope warning names the shared budget.
2026-11-13 20:15:26 -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