Commit Graph
403 Commits
Author SHA1 Message Date
BFlat 31eb3b0d1e Merge pull request #7285 from dotCooCoo/fix/pdf-warped-image-written-once
PDF export: a warped image writes its pixels once for all its pieces
2026-11-14 05:39:34 +07:00
BFlat 4558196e16 Merge pull request #7053 from dotCooCoo/feat/warichu
Type: Warichu stacks selected characters on lines inside their line
2026-11-14 04:32:40 +07:00
dotCooCoo 55f43d2acb PDF export: a warped image writes its pixels once for all its pieces
With downsampling on, each piece of an image bent by a Warp effect was
resampled for its own placed size, so a warp wrote one image XObject for
each size a piece was placed at (four for a 4 x 4 warp that stretches
across, eight for a colorized one with its soft masks). The pieces are
now resampled for the widest and the highest size any piece places the
image at, and all paint that one image. Pieces off the page count too,
and another placement of the same image keeps its own size.

Without downsampling, a colorized image and a CMYK image with a grid
mask no longer key their cache by placed size, so each is decoded and
encoded once for all the sizes it is placed at, as plain images are.
2026-11-13 12:54:12 -08:00
BFlat 9107dad274 Merge pull request #7194 from dotCooCoo/fix/item-3829
Envelopes: a partly transparent image keeps its alpha where its warp pieces overlap
2026-11-14 03:23:28 +07:00
dotCooCoo fdedfb0e59 Merge main into feat/warichu 2026-11-13 11:59:22 -08:00
BFlat 1c1bb2f96e Merge pull request #7191 from dotCooCoo/feat/gradient-hue-blend
Gradients: Hue Clockwise and Hue Counterclockwise mix stops around the hue wheel
2026-11-14 01:53:39 +07:00
BFlat d533018fd5 Merge pull request #7180 from ruchirguitar/feat/6740-type3-named-groups
feat(pdf): preserve Type 3 font text runs as named groups (#6740)
2026-11-14 01:53:02 +07:00
dotCooCoo 4d4d7ee1a7 Envelopes: opaque pixels of a warped image stay opaque where its pieces overlap
In SVG and PDF output, each piece of a warped image whose pieces can show
through was drawn through a mask of every later piece that reaches it. On a
later piece's antialiased edge the viewer multiplies the earlier piece's
coverage by the mask and draws the later piece over it, so an image with
both opaque and partly transparent pixels came out lighter at its opaque
pixels along the triangles' edges (alpha 184 of 255 in the new SVG test).

A later piece now goes into an earlier piece's mask only when a pixel of
either piece's image within 2 pixels of their overlap is less than opaque
(vectorcraft_effects::WarpSeams). Where two pieces overlap over opaque
pixels, the later one is drawn over the earlier one without a mask.
2026-11-13 10:36:16 -08:00
ruchirguitar a52890ec0f fix(pdf): blend mode inheritance for Type 3 fallback, CharProcs budget via decoded_within, and docs clarification 2026-11-13 23:00:54 +05:30
dotCooCoo 0663c76be1 Envelopes: a partly transparent image keeps its alpha where its warp pieces overlap
An envelope or the Warp effect cuts an image into triangle pieces that
reach a little past their edges, so neighbors overlap and no seams show.
On an image with alpha, the overlap drew that alpha twice: a 50% image
came out about 75% opaque along every cell edge and diagonal.

- The pieces now form a knockout group, and each piece is marked as a
  warp piece (`warp_piece`) whose knockout shape is its whole triangle,
  so where pieces overlap only the top one draws.
- The canvas knocks each piece out by its triangle at full coverage.
- SVG and PDF draw the pieces of a partly transparent image (its pixels,
  opacity, color mask or colorize paint) through one mask each, of the
  later triangles that reach it; pixels on a triangle's antialiased edge
  come out slightly lighter there. Pieces of an opaque image are drawn
  one over another as before.
- SVG writes one copy of the image for pieces cut by opacity masks
  (Preserve Shape Using Transparency) too.
- A cell count past the generated-object budget makes an empty group
  instead of overflowing.

Docs: docs/target-app-parity.md.
2026-11-13 08:38:48 -08:00
dotCooCoo 5f77b65aa2 Gradients: Hue Clockwise and Hue Counterclockwise mix stops around the hue wheel
The Gradient panel's Method menu gets two methods of VectorCraft's own
beside Classic and Perceptual. They mix a linear, radial, conic or
diamond gradient's colors around the hue wheel: hue, saturation and
brightness each change evenly from one stop to the next, and the hue
angle keeps one direction, as the fixed-direction rules of
https://www.w3.org/TR/css-color-4/#hue-interpolation do. Hue Clockwise
lowers the angle (red, magenta, blue), which is clockwise on the color
wheels, and Hue Counterclockwise raises it (red, yellow, green).

Two stops whose hues are less than half a color level apart count as
one hue and keep it, so a color and a tint or shade of it do not turn
the whole wheel. A stop whose RGB numbers are less than half a color
level apart is gray and takes the hue of the stop it mixes with, and
black takes that stop's saturation too.

- `paint.editGradient` and `paint.setFill` take `method: hue-clockwise`
  or `hue-counterclockwise`, in any case, with a space or an underscore
  for the hyphen or without it; other spellings are an error. The native
  file writes `HueClockwise` and `HueCounterclockwise`.
- The canvas and raster exports draw the gradient through stops on its
  curve, within half a color level.
- Reverse turns the method the other way with the stops, and a Reflect
  spread is repeated from the curve's stops, so both keep the colors.
- SVG and PDF write the gradient as an RGB image, CMYK and spot color
  stops included, with the spot warning. EPS writes a shading in process
  colors with a warning for spot stops. A legacy .ai file and the .ai
  editing data get the colors between the stops as stops of their own,
  in process colors, at most 256, with a warning. CSS gets those stops
  too.
- The `method` error names the four values, in every catalog.
- The Method menu is as wide as its longest name in the interface
  language, within the panel.

Docs: docs/mcp.md, docs/plugins.md, docs/target-app-parity.md, ROADMAP.
2026-11-13 08:26:57 -08:00
dotCooCoo cd7e209934 PDF: pages longer than 200 in are written at full size in points by default
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.
2026-11-13 08:10:42 -08:00
ruchirguitar 66513d47fa feat(pdf): preserve Type 3 font text runs as named groups (#6740) 2026-11-13 21:25:10 +05:30
dotCooCoo 7b30424538 Merge main into feat/warichu 2026-11-13 04:06:56 -08:00
dotCooCoo 199a9dbce3 Merge main into feat/warichu 2026-11-12 22:28:38 -08:00
dotCooCoo 226ac437b9 Type: Warichu stacks selected characters on lines inside their line
The Character panel menu has Warichu and Warichu Settings… with Show East
Asian Options. Warichu characters are set at a percentage of their size
and stacked on 1 to 6 lines inside their line: one above the other in
horizontal type and side by side in vertical type. Warichu Settings sets
Lines, Line Gap, Scale and Alignment.

- text.setFormat and text.setRangeStyle take warichu, warichuLines,
  warichuGap, warichuScale and warichuAlign; ui.warichuSettings opens
  the dialog.
- A stretch of warichu characters is one block that stays whole on one
  line. The canvas and every export draw the stacked lines; SVG, PDF and
  the .ai writers write such type as outlines, as they do ruby. Type on a
  path sets the characters at their own size.
- The attributes are saved natively, carried by character styles and
  translated in every complete catalog.

Docs: docs/mcp.md, docs/type-parity.md.
2026-11-12 21:13:21 -08:00
Don Omondi b0cc3eb13a Merge remote-tracking branch 'upstream/main' into fix/pdf-empty-actualtext-art-6971 2026-11-12 23:29:01 -05:00
BFlat f062dd7ed2 Merge pull request #6932 from dotCooCoo/feat/dcs-linked-spot-plates
Place: DCS files link with their spot plates as spot swatches and separate on their own inks
2026-11-13 11:27:13 +07:00
BFlat 465091d7d2 Merge pull request #7031 from dotCooCoo/fix/followup-6920
Print: notes of what a print loses come before notes on options
2026-11-13 11:26:54 +07:00
BFlat 21d8d322a4 Merge pull request #7024 from mockydevs/fix/pdf-mark-text-needs-craft-fonts
PDF tests: the mark-text regressions skip without the craft-fonts Noto Sans Arabic
2026-11-13 11:26:31 +07:00
Don Omondi 8ba280ec44 Merge remote-tracking branch 'upstream/main' into fix/pdf-empty-actualtext-art-6971
# Conflicts:
#	docs/file-format-parity.md
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-12 22:40:11 -05:00
dotCooCoo 9c1c7dee7e Print: notes of what a print loses come before notes on options
A print to a file and the print preview list their notes as saves and
exports do since #6920: what the job leaves out of the document or prints
differently first (art outside the imageable area, type in a fallback
font, transparency flattened for PostScript), then the notes on the
options (halftone screens and a fixed flatness that aren't written, copies
per sheet that don't fit, a printer profile left out, ink options that
name no ink). Each kind keeps the order it is given in.

The print layout, the PDF print and the PDF print plan return the notes
on the options in `setting_notes` beside `warnings`, as `ExportReport`
does. The status message after a print to a file names the first note,
so a fixed flatness no longer hides type printed in a fallback font.
2026-11-12 19:13:13 -08:00
dotCooCoo f6d8af3ed6 Merge main into feat/dcs-linked-spot-plates 2026-11-12 19:09:51 -08:00
dotCooCoo 99f896f9b8 Place: DCS links follow their plate files, clips and document swatches
- The link watch and links.updateChanged look at a DCS file's plate files
  of their own, so a changed plate file is read again.
- links.update and links.relink apply the file's clipping path to the
  images in symbols, graph designs, patterns and masks too. When the new
  file has no clipping path, a clip group holding the old file's clipping
  path loses that path and stays as a plain group of the image, keeping
  its id, name, visibility and transparency. The image keeps that path with its plates to tell it from a
  clipping mask made in the document; a clipping path given another fill
  rule in the document stays. An even-odd clipping path in the file is
  kept as the same area under the nonzero rule.
- links.update and links.relink return the swatch warnings file.place
  gives, including two files that add one ink in two colors.
- links.relink with copy fails for a DCS file with plate files of its own.
- file.place answers the image id of a clipped DCS placement as image,
  and checks page and crop for a DCS file as it does for an EPS file.
- Print separations and Separations Preview take a spot plate's color
  from the document's swatch of its ink, and a reduced image's plates
  keep their coverage.
- Show DCS Transparency Interactions counts a transparent DCS image and
  characters filled or stroked with a transparent gradient.
- %%PlateFile names keep their spaces, and header bytes that are not
  UTF-8 are read as Latin-1.
- A plate program that draws more than one image, art besides its image,
  or its image through a clipping path is an error naming the plate
  instead of printing the wrong ink.
- Nested clipping paths around the composite clip the image together.
- A kept image with more plates than are read, or more TIFF directories
  than its composite and plates, is the CMYK image of its composite
  only, not a set of plates cut short.
- swatch.unused counts a spot or process swatch as used only while an
  image the art shows has a spot plate of its name.
2026-11-12 18:43:04 -08:00
Don Omondi 4cbd0f83d7 PDF tests: the mark-text regressions skip without the craft-fonts Noto Sans Arabic 2026-11-12 21:08:34 -05:00
dotCooCoo df155042d4 Merge main into feat/image-color-mask 2026-11-12 17:40:13 -08:00
Don Omondi d5f0fe3a3f PDF import: glyphs in a span with an empty ActualText come in as outlines (#6971) 2026-11-12 19:15:40 -05:00
BFlat 9861e7f927 Merge pull request #6920 from dotCooCoo/feat/export-notes-loss-first
Save and Export: notes of what the file loses come before notes on options
2026-11-13 05:23:53 +07:00
dotCooCoo 18aed1da4e Merge main into feat/dcs-linked-spot-plates 2026-11-12 12:45:18 -08:00
dotCooCoo 15ffb4ec01 Merge main into feat/export-notes-loss-first 2026-11-12 12:45:09 -08:00
dotCooCoo 7dd161cc49 Place: DCS files link with their spot plates as spot swatches and separate on their own inks
File › Place with Link reads a DCS 1.0 or 2.0 file (an EPS file whose
header names one EPS program per printing plate) as one linked image of
its plates. Each spot plate adds a spot swatch in the CMYK values the
file gives, and the clipping path the file's composite is drawn through
clips the image. document.open, file.place without link or from bytes,
and links.embed refuse a DCS file and change nothing.

- The screen, composite print and exports show the plates mixed into
  CMYK. Separations Preview and print separations show each plate on
  its own ink; a spot plate prints as its CMYK values when spots print
  as process.
- links.list answers the format DCS, and with dcsTransparency marks the
  DCS images that are transparent or overlap transparent objects (the
  Links panel menu's Show DCS Transparency Interactions).
- swatch.unused leaves out a spot swatch while a DCS image has a plate
  of its ink.
- links.update and links.relink read the plates and the clipping path
  again, and the link shows as modified when one of its plate files
  changes or is gone.
- The plates go on the first plate's pixel grid, grown to hold every
  plate where it prints; a plate of another size or position is
  resampled onto it.
- A file may name 64 plates, a plate file may be 1 GB, and the plates
  together may hold 512 MB of ink amounts. A file naming more plates is
  an error.

Docs: docs/mcp.md, docs/target-app-parity.md, docs/file-format-parity.md.
2026-11-12 09:30:20 -08:00
dotCooCoo fe34c2b818 Merge main into feat/custom-arrowheads 2026-11-12 09:23:20 -08:00
dotCooCoo 8d27e53115 Merge main into feat/image-color-mask 2026-11-12 08:56:33 -08:00
BFlat 5f3c7f5425 Merge pull request #6906 from ruchirguitar/fix/pdf-indic-text-5235
PDF import: Indic type that would not draw as the file does keeps the file's glyphs (#5235)
2026-11-12 23:52:49 +07:00
dotCooCoo 766e291e3c Save and Export: notes of what the file loses come before notes on options
Each writer marks its notes as a loss (something of the document that the
file leaves out or that reaches it changed) or as a note on the options
(an option it didn't apply or applied another way while the art reaches
the file as it looks, or something an option turns off). The PDF, SVG,
EPS, legacy .ai, DXF and HP-GL writers return their notes on the options
in a list of their own (`setting_notes`) beside `warnings`, and the
engine's `Encoded` does the same.

The replies of the save and export commands, and of
`clipboard.exportPdf` and `clipboard.exportPng`, list the losses first,
each kind in the order the writers gave them, across every file that
Export for Screens writes. The status bar names the first note, so an
export to lossy WebP of type in a font that isn't installed now names the
fallback-font note instead of the lossy WebP note. A print to a file
keeps the order its notes are given in.
2026-11-12 08:33:57 -08:00
dotCooCoo e54519d6bd Merge main into feat/image-color-mask 2026-11-12 07:51:12 -08:00
ruchirguitar f18fb4e92d PDF import: Indic type that would not draw as the file does keeps the file's glyphs (#5235)
Gujarati text from a PDF came in jumbled even with its fonts installed:

- A glyph with no advance (a vowel sign or anusvara set over its letter)
  was taken for vertical type and opened as an object of its own, which
  type then drew on a dotted circle. In a font the file writes
  horizontally it now stays on its line.
- A line read glyph by glyph is not always the text that was set: the
  file draws a vowel sign before the consonant it follows, and may not
  name a conjunct. A line with characters of U+0900 to U+0DFF is now set
  again and its glyphs compared with the ink the file drew; when they
  differ the line keeps the file's glyphs as outlines, with a note.

Tests: crates/pdf/src/tests/reshaped.rs (two fail without the change).
2026-11-12 20:56:16 +05:30
dotCooCoo 91d705e155 Gradients: repeat or reflect a gradient's stops a set number of times
A linear, radial, conic or diamond gradient has a spread: Pad (the
default, as before), Repeat or Reflect, with a count of 1 to 100
(VectorCraft's own limit). Repeat and Reflect run the stops that many
times along the vector (around the turn for a conic) and keep going past
both ends, Reflect running every other run backwards, as SVG's
spreadMethod does.

The Gradient panel has a Spread menu and a Repeats field, and the
Gradient tool marks where the runs meet. paint.setFill and
paint.editGradient take `spread` and `repeats`; bad values are errors.
Presets, swatches, blends, strokes along or across a path, Outline
Stroke and Object › Expand follow the spread; Expand gives each run the
same whole number of objects, and Outline Stroke's mesh keeps the color
on each side of a sharp step between two stops at one offset.

SVG writes and reads spreadMethod: SVG import now reads a repeating or
reflecting gradient as one that repeats or reflects once, instead of
expanding its stops over the shape. CSS writes repeating gradients.
PDF writes a conic's sweep shading over one run. PDF, EPS, legacy .ai
and the .ai editing data write the other kinds with their stops
repeated across the shape: at most 256 runs and 16,384 stops (256 stops
in .ai files), and for a radial or diamond no farther than 65,536 runs
from its center, with a warning past those. PDF import now finds sharp
steps in any axial or radial shading instead of blurring them.

Docs: docs/mcp.md (Spread), docs/target-app-parity.md, docs/gaps.md.
2026-11-12 06:52:38 -08:00
dotCooCoo 72fb8fe81d Image Tools: masked images count as see-through in legacy .ai and pattern tiles
- The legacy .ai and the check for see-through images in pattern tiles
  read a color-masked image's masked pixels, as the flattener does. A
  legacy .ai flattens a masked opaque image with the art under it, or
  leaves it out with `transparentImages: "omit"`, and a pattern tile that
  holds one is expanded before PDF/X-1a, PDF/X-3 and legacy .ai output
  flatten it.
- Printed separations check whether a colorize paint shows on the masked
  pixels, as the canvas does, rather than on the image's own pixels.
- A saved mask that leaves out `contiguous`, `tolerance` or `softness`
  reads them as the command's defaults: true, 10 and 10.
- Remove Background is unchanged on this branch. Its refusal of a
  grayscale image colorized with a process color is left for a separate
  pull request.

Tests: legacy_ai_flattens_a_masked_image_as_a_see_through_one,
a_pattern_tile_with_a_masked_image_counts_as_see_through,
pdf_x1a_and_x3_flatten_the_hidden_pixels (PDF/X-3 added),
separations_colorize_masked_pixels_whose_own_pixels_are_a_preview,
a_record_without_settings_reads_the_defaults, and the dialog's query on a
linked image at its preview.
2026-11-12 06:27:59 -08:00
dotCooCoo 0779da299b Image Tools: Color Mask hides chosen colors of an image while its pixels stay
Object › Plug-ins › Image Tools gains Color Mask… (`addon.image.colorMask`),
Remove Color Mask and Apply Color Mask. Color Mask hides colors of the
selected images without changing their pixels. It matches colors as Remove
Background does: the edge color, the corner color or picked colors, with
Contiguous, Match, Tolerance and Softness. The mask is kept with the image
object and saved with the document: its settings, and a PNG of the image's
pixels with the hidden colors made clear, at the source's depth with its
color profile and resolution. It is a VectorCraft addition.

- The canvas (clip groups and white-shape opacity masks included),
  printing and separations, PDF (soft masks of CMYK images included), SVG,
  EPS, the raster formats, the legacy .ai and .ai editing data, EMF/WMF,
  DXF and the flattener draw the masked pixels. A linked image stays
  linked, and an output that would refer to its file writes the masked
  pixels instead.
- Copy and paste, placing a document and placed documents carry the masked
  pixels with the image, under the names they are given there.
- The dialog opens on the selected image's mask settings, with a Preview.
  Without settings, the command returns them and changes nothing.
- Setting, removing and applying a mask are each one undo step, and no
  step is added when nothing changes. Apply makes the masked pixels the
  image's own and embeds a linked image. A mask that hides nothing is only
  taken off, and the image keeps its pixels and its link.
- When an image's own pixels are replaced (Update Link, Relink, Crop
  Image, a recolor, a linked file read again on open), its mask is made
  again for the new pixels, in every art tree and in opacity-mask art.
  Crop Image cuts the image's own pixels. When the new pixels can't be
  masked, the mask keeps its settings and hides nothing.
- Objects in `ids` that are not images, CMYK images, linked images that
  show their preview, images past the decode allowance, masks that would
  hide every pixel, and grayscale images colorized with a process color
  are refused. The Eyedropper, Object Mosaic, Create Gradient Mesh, Crop
  Image's trim and Image Trace read the image's own pixels.
- An image is selected by a click anywhere in its frame, as before.

Remove Background now also refuses a grayscale image colorized with a
process color. Its result has an alpha channel, and a process color is
refused on a grayscale image with transparency.

Docs: docs/mcp.md (Image Tools add-on › Color Mask),
docs/target-app-parity.md.
2026-11-12 05:17:01 -08:00
dotCooCoo 5e80810605 Merge main into feat/custom-arrowheads 2026-11-12 05:00:21 -08:00
Taha-Mahmoodi 3eb9e0271c Merge remote-tracking branch 'origin/main' into fix/import-document-title
# Conflicts:
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-12 15:18:59 +04:30
BFlat 4c2912100e Merge pull request #6795 from dotCooCoo/fix/pdfx-check-skips-strings
PDF/X: names inside a string or a comment no longer fail the standard check
2026-11-12 14:16:50 +07:00
dotCooCoo 264eeec475 Merge main into feat/custom-arrowheads 2026-11-11 22:30:03 -08:00
dotCooCoo c1f7e2eeaf Stroke: custom arrowheads from an arrowheads file join the arrowhead menus
The Stroke panel menu's Edit Arrowheads… (stroke.arrowheads.edit) opens
Arrowheads.vectorcraft next to the preferences, creating it with one
example head when it is missing. Each symbol in the file is one head,
listed by name after the built-in heads in both arrowhead menus: it
points right, its registration point is the tip, and its height is drawn
as wide as the built-in heads. The file is read at startup and again
each time VectorCraft saves it; stroke.arrowheads.reload and
stroke.arrowheads.list read and list it.

Arrowhead gets a Custom variant, appended after the built-in names, that
carries the head's name and outline, so a document that uses one draws,
saves, reopens and exports it without the arrowheads file. stroke.set
takes {"custom": name} or the {"Custom": {name, path}} form that
document.inspect reports.

Part of #5421.
2026-11-11 21:52:46 -08:00
BFlat 4eb0915795 Merge pull request #6781 from dotCooCoo/feat/diamond-gradient
Gradients: diamond gradients run the stops from the center out to a square
2026-11-12 12:40:46 +07:00
dotCooCoo a07cdf87f0 PDF/X: names inside a string or a comment no longer fail the standard check
The check that a PDF/X-1a or PDF/X-3 file has no transparency read names
in literal strings and comments as syntax. The file identifier is a
base64 hash of the file, so a file could now and then hold `/BM` or
`/Lab` there and its export was refused as having blend modes or Lab
colors. The check now leaves out the text of literal strings and
comments as well as stream data.
2026-11-11 21:29:50 -08:00
dotCooCoo 66d21471ae Gradients: diamond gradients run the stops from the center out to a square
A new gradient kind, `diamond`, runs its stops from the center (the
start) out to a square with a corner at the end of the vector; the
aspect stretches the square across the vector into a rhombus. The
Gradient panel's Type row has a Diamond button, the Gradient tool draws
the square with the aspect handle and center ring, and a gradient
fitted to an object covers its box.

- Model and canvas: the level is |x| + |y| in the square's frame; a
  square with no area (no vector, an aspect of 0, numbers out of range)
  paints the last stop. The canvas draws it as pixels, out to a
  stroke's miters, caps and arrowheads. Transforms keep the vector and
  take the mapped size across it as the aspect.
- Commands: `paint.setFill`, `paint.editGradient` and
  `paint.setGradientGeom` take `kind: "diamond"`; a negative aspect or
  a focal point is an error. A conic or diamond gradient that a plug-in
  returns with a focal point loses the focal point.
- Gradient tool: dragging the aspect handle of a radial or diamond
  gradient whose file gave it a negative aspect now sets a positive
  aspect; only a conic's negative aspect mirrors it.
- Export: PDF, SVG, EPS and legacy .ai write four linear gradients, one
  for each quarter of the square, clipped to the shape (PDF as axial
  shadings). PDF and SVG write an image for translucent stops, a
  dithered fill or a flat square, and for the Perceptual method unless
  PDF writes the stops as spot color shadings. SVG writes a diamond on
  type characters as a radial gradient through the corners, and so
  does CSS. A swatch library saved as CSS gets four corner layers, a
  value for the `background` property (a circle when the swatch is
  turned by an angle that is not a multiple of 90 degrees). The .ai
  editing data holds a radial gradient through the corners. The
  document exports give a warning.
- SVG export: a stroke drawn as an image, as conic wedges or as diamond
  quarters now covers the miters, caps and arrowheads that reach past
  its paint box.
- PDF import reads a function-based shading whose color is the same
  along each square about the origin of its space as a diamond.
- Object > Expand gives nested squares or a mesh of rings.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-11 20:27:48 -08:00
dotCooCoo b403fe230f Merge main into fix/pdfa-14-long-pages 2026-11-11 18:43:27 -08:00
BFlat a118925177 Merge pull request #6668 from storytold/fix/sec-pdf-scan-budget
PDF: note fonts once per walk, place repeated rasters without converting again, check image headers before embedding
2026-11-12 09:23:42 +07:00