graphicStyle.new linked the object it was made from, the art of a column
or marker design in a graph series included, and graphicStyle.redefine
gave the new look to every object still linked to the style. Redefining
the style from another object then restyled that art, which the graph
draws again from the design.
- graphicStyle.new makes a style from the art without linking it.
- graphicStyle.redefine leaves the art's look as it was and unlinks it,
as an edited object is, whether the art is a linked object (as in a
document saved before this change) or the source.
Docs: docs/mcp.md, the params text of graphicStyle.new and
graphicStyle.redefine.
A gradient vector drawn on the art, a click that applies one, and the
dragged start and end handles snapped through snap_draw, which gathers
the bounds and anchors of the art only. Path segments, View › Snap to
Glyph's guides and the construction guides through the vector's start
did not pull them, and a click applied the gradient from the pointer
rather than from the snapped point. They now snap through DrawSnap, as
the Pen and Line Segment tools do:
- The press gathers the targets, for a vector drawn on the art and the
start and end handles only, and the drag keeps them. A click applies
the gradient from the snapped press.
- A dragged end or handle leaves its start as a Line Segment's end does:
it lands on the construction guides through the start, and with Shift
it keeps to 45° steps from the Constrain Angle and snaps along them.
- The pointer hovering where a press would draw a vector (anywhere with
art selected, over art with nothing selected), and not over the
annotator, shows the guides of the point the vector would start on.
A press that snaps onto a nearby target no longer starts the drag
early: the 3 px drag threshold counts from where the pointer was
pressed, not from the snapped start.
The Ukrainian catalog translated Color Library and Color Library… as
"Бібліотека квітів" (library of flowers). Both rows now read
"Бібліотека кольорів", the genitive plural of колір used elsewhere in
the catalog. A test checks both labels through the catalog lookup.
No other Ukrainian row uses квіт- for color. The Russian, Bulgarian,
Bosnian, Czech and Polish labels already name colors.
The palette listed the Layers panel's Delete Selection twice: as
Window › Layers › Delete Selection, which ran layer.delete and deleted a
layer holding art without asking, and as a bare Delete Selection, which
ran ui.layerDelete and asked first.
- The palette now lists one Window › Layers › Delete Selection result,
which runs ui.layerDelete, so a pick asks before deleting a layer or
sublayer that holds art. Scripts and the control channel still run
layer.delete at once.
- New Brush…, Brush Options…, Symbol Options…, Import SVG Filter… and
Convert to Text were also listed twice under the same name, once as
the engine command, which the palette ran with no params. Each is now
listed once, as the UI command that opens its dialog or file chooser
or acts on the edited paragraphs.
- A search for a wrapped engine command's id or menu path still finds
the one result.
Docs: docs/target-app-parity.md (Layers panel deletion).
untranslated_report lists 167 messages under "messages, all 23 languages
checked". zh-hant.tsv gains an @msg row for 114 of them, in one block at
the end of the file: image export and encoding errors, color profiles,
color books and swatch exchange files, binary DXF and DWG import, 3D and
Revolve limits, and script, zip, line and file errors. Placeholders,
parameter names and literal values stay as the English writes them.
The other 53 are left to the open pull requests that translate them
(composite fonts, SVG filters, read roots and graph design).
A <tspan>, <textPath> or <a> inside a <text> whose unicode-bidi is embed
now gives its characters its direction as their Character Direction. An
element with normal stays in its parent's embedding, unicode-bidi is not
inherited (inherit takes the parent's value), and the <text> keeps its
own paragraph direction. A run that SVG export writes with direction and
unicode-bidi="embed" now opens with its Character Direction again.
Character Direction holds one level of embedding and no override or
isolation, so bidi-override, isolate and isolate-override are imported
as embeddings in their direction, plaintext as an embedding in the
direction of its first strong character, and an embedding inside
another as an embedding of its own, each with an import warning.
unicode-bidi: plaintext on the <text> runs and anchors each paragraph
in the direction of its first strong character.
https://www.w3.org/TR/SVG11/text.html#RelationshipWithBi-directionalityhttps://www.w3.org/TR/css-writing-modes-3/#unicode-bidi
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.
untranslated_report lists 167 status and error messages that no
complete-message catalog translates. zh-hans.tsv gains 114 @msg rows for
the ones no open pull request covers: 3D and Revolve limits, image export
and encoding errors, color profiles, color books and swatch exchange
files, binary DXF and DWG import, path operations, swatch, graphic style
and action set libraries, and zip, script and regular expression errors.
Placeholders, backticked names, command ids and listed values stay as the
English writes them.
The other 53 (composite fonts, SVG filters, read roots and graph design)
are left to #7211, #7378 and #7405. docs/localization-parity.md and
docs/target-app-parity.md give the new counts: 3,554 @msg rows, and 55
messages the report lists for zh-hans, all of them translated by open
pull requests.
A graph keeps paints for its series and labels, and character and
paragraph style names for its labels, which each redraw gives the
marks and labels. Copy did not follow them, so a graph pasted into
another document left those swatches and styles behind, and a paste
that renamed them left the graph pointing at the old names.
Copy now collects them and paste relinks them, as it does for type.
Paste without Formatting drops the labels' style names, so it still
leaves text styles behind.
The Danish catalog had 1,033 `@msg` rows and 47 `@msgplural` rows, and
Danish was not in COMPLETE_MESSAGES, so with the interface in Danish
script errors, plug-in manifest and permission errors, parameter
schema errors, 3D effect refusals, file-reader errors and data-set
messages showed in English.
- da.tsv gains the 602 `@msg` rows and the one `@msgplural` row that
the German, Czech, Spanish and French catalogs have and Danish
lacked. The `@msg` rows are one block with a header comment on
their conventions. Backticked names, command ids, double-quoted
values and bare true, false and null stay as the English writes
them.
- da joins COMPLETE_MESSAGES, so the message tests that iterate the
list check Danish too, and the untranslated report lists Danish's
missing messages. It lists the same set for Danish as for Czech,
Spanish and French.
- The registry comment, docs/development.md, the Danish row and
introduction of docs/localization-parity.md, and the interface
languages line of docs/target-app-parity.md list Danish among the
languages that translate messages.
On the core Wayland clipboard, a read waited for the app that copied to
close its pipe, and a send wrote until the app that pastes took all of
the data. An app that left its pipe open and stopped held the one read
worker, so later pastes failed at once, or held one of the eight send
threads until it closed its end.
Reads and sends now use the pipe nonblocking and wait for it with poll.
When no byte moves for 2 s (VectorCraft's own limit, the existing text
wait) the read fails without pasting partial data and the send stops;
both close their pipe. The wait starts again after each byte that moves,
so a large transfer that keeps going is not cut short.
Quitting can wait up to 27 s for the clipboard handles to let go before
eframe closes the windows. winit cannot hide a native Wayland window, so
the main window stayed on screen for that wait, and the X11 windows of
floating panels and documents were not hidden at all.
- A native Wayland main window is unmapped by attaching no buffer to its
surface. The window and its connection stay open for the Wayland
clipboard. An X11 main window, XWayland included, is hidden as before.
- On Linux the X11 windows of floating panels and documents are recorded
as eframe creates and drops them (viewport hooks), and quitting unmaps
them through a second X11 connection before the wait.
- The new module apps/vectorcraft/src/quit_windows.rs replaces
app::hide_before_teardown, with tests of which windows are hidden or
unmapped. portal_save's Wayland surface helper is shared with it.
The comment on the zigzag cases said the open zigzag grown by 1.5 leaves
stroker loops whose faces the distance test drops. With the turned branch's
distance test measuring points in the turned frame, or dropping no face at
all, the three zigzag cases still pass and only the plate case fails (201
contours instead of 101). The comment now says what the zigzag cases check:
one turn for the low path, none for the path stood on end, and the same
region from both. The plate comment says its narrow holes are dropped by
the distance test measured at points turned back into the plate's frame.
A drag of art across the document tabs ended whenever the source
document's revision changed. Since #7173, bringing a document with other
assigned color profiles to the front raises every open document's
revision so that each redraws in the new profiles, so holding art over
such a tab switched to it and then canceled the drag before the drop.
The drag now keeps the source document it left and ends only when that
document's content changes (DocState::same_content). A redraw keeps it,
and so does type measured again when the source comes back to the
front, which replaces the document without editing it.
A raster effect (Drop Shadow, Outer Glow, Gaussian Blur and the other
effects that paint pixels) on a symbol instance's topmost fill now draws
on each filled shape of the symbol's art, and one on its topmost stroke
draws on each stroked shape, after any geometry effects listed before
it. The same rules as for geometry effects apply: only a visible fill or
stroke with an opacity above 0 counts, a group's own fills and strokes
in the art take the effect, and an instance inside the art passes it on.
The canvas, Use Preview Bounds and the drawn bounds, SVG and PDF export
draw it, and Object > Expand Appearance is enabled for such an instance:
a shadow or glow becomes an image under the instance, and a blur,
feather or inner glow replaces it with the image, in one undo step.
Existing documents with a raster effect on a symbol instance's fill or
stroke draw differently: before, the effect drew nothing.
Character panel > Tsume, shown with Show East Asian Options, takes away a
percentage of the blank space on each side of a character's ink, inside
its own width, in horizontal type. The value is from 0 to 100, 0 by
default. 50 halves that space and 100 sets the ink against the
characters before and after it; the glyph keeps its shape. A character
without ink, such as a space, keeps its width, and a ligature or a
letter with its marks takes the value of its first character. The
font's pair kerning, tracking, manual kerning and Insert Aki are added
after it, and justification keeps it. Vertical type keeps its spacing.
- text.setFormat and text.setRangeStyle take `tsume`; a value that is
not a number or is outside 0 to 100 is refused, naming the key.
Character styles carry it, and a file holding a value outside the
range opens with the nearer end.
- The Character panel's Tsume field has 0, 25, 50, 75 and 100 in its
menu, and Reset Panel sets it to 0. Character Style Options shows it
in Advanced Character Formats.
- Live SVG text places each character Tsume moves, and type on a path
with Tsume is written as outlines.
Docs: docs/mcp.md (Tsume, Character Style Options fields),
docs/target-app-parity.md.
The centre-lines class gains a mixed-width body scene: one disc of radius
24 px with arms of 2, 3 and 5 px that start inside it, Stroke 6 px, and no
other ink. A test checks that the scene is one connected shape and that
both the anti-aliased and hard input trace as one fill and three strokes
that reach all three free ends.
docs/image-trace-quality.md's centre-lines section is measured again on
current main (24 scenes, two runs identical in every column but ms). The
new scene finds 100.0% of its arms with 99.3% / 98.3% of the disc filled;
mix now traces as 6+3 paths with 99.9% / 99.8% found and 7/7 ends, where
the earlier whole-blob rows showed 3+1, 57.3% and 6/7. All other rows
are unchanged except ms.
With Shadows on, Extrude & Bevel, Inflate, Rotate and Revolve built
every solid twice: once for the art and again for the shadow. The build
that draws a solid now also keeps the faces its shadow is cast from and
the projection they were built with, and the shadow is cast from them.
The art and the shadow are unchanged.
- three-d: the solid builder can keep the projected facets and the
view-space faces together (`Keep::Both`); `extrude_shadowed`,
`plane_shadowed`, `inflate_shadowed` and `revolve_shadowed` return
both, and `ShadowCaster::add_solid` adds the kept faces. Revolve's
sweep draws the surface and keeps the shadow's faces in one pass; a
shadow past its limits still gives the same error while the surface
draws.
- effects: the solids drawn hand their faces to the shadow. A stroke's
solid left out of the art is still built for the shadow alone, as
before.
Tests compare each solid and its shadow with the two built apart, to
the bit, and count the solids built for a shadowed object.
A paragraph whose characters differ in line metrics, in area type that is
not a rectangle or that wraps around an object, was broken line by line
with the Single-line Composer when the frame could not hold all of it.
The lines the frame holds are now composed with the whole paragraph: a
line the frame has no room for, and every line after it, is measured as
wide as the span of the last line set in the frame, less its indents.
Those lines overflow, or go on in the next threaded frame, which composes
them again at its own widths. A paragraph whose first line has no room,
and a search that passes its limits, still fall back to Single-line.
Docs: docs/mcp.md, docs/target-app-parity.md.
untranslated_report lists 167 messages under "messages, all 23 languages
checked". ru.tsv gains an @msg row for 114 of them, in one block at the end
of the file: image export and encoding errors, color profiles, color books
and swatch exchange files, binary DXF and DWG import, 3D and Revolve limits,
and script, zip, line and file errors. Placeholders, parameter names and
literal values stay as the English writes them.
The other 53 are left to the open pull requests that translate them
(composite fonts, SVG filters, read roots and graph design).
document.exportSelection run with no params or {} (a shortcut, or an
automation call) wrote the picked file straight away with each format's
defaults: a PDF used the default preset, so Save PDF's options, such as
writing long pages in points, could not be chosen. It now takes Export
As's route after the save panel: Save PDF without its Artboards
section, SVG Options without its artboards, the raster options, EPS
Options, DXF Options, Text Export Options with Selection Only on, or an
exporter plug-in's parameters. OK writes the selection alone, cropped
to it, with the chosen options. While a dialog is open the call returns
null, and OK returns what file.exportAs returns, without format or
bounds.
With a path or any option it still writes straight away.
- file.exportAs takes exportSelection: true and then writes the
document that document.exportSelection writes
(fileio::selection_doc), without artboard choices. The options
dialogs and the replace-file questions pass it on.
- Nothing selected stops before the save panel.
- SVG Options opened by Export Selection leaves the remembered Use
Artboards as it was.
- Exports through file.exportAs (Export As and the options dialogs)
apply Appearance of Black's rich black, as document.export does.
Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
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.
A radial gradient whose color line runs past 0 or 1 can get a circle
with a negative radius once its stops are normalized to 0..1. Circles of
a negative radius are not drawn: only the side of the circle of radius 0
(the tip of the cone) where the radius is positive is painted
(https://learn.microsoft.com/en-us/typography/opentype/spec/colr, Radial
gradients). Before:
- As vector art, a padded gradient with a stop before 0 and its centers
apart was focused on the start circle's center instead of the tip, and
one with its centers together got stop offsets below 0.
- Drawn into an image (a glyph with a sweep gradient, a Porter-Duff
composite or a repeating gradient), any such gradient filled the glyph
with its first stop's color.
Both now recast the circles so neither radius is negative. With pad, the
stops on the side that is not drawn become one stop at the tip with the
color there; stops at the tip stay, so a sharp change of color there
keeps the color on the drawn side. With repeat and reflect, the circles
move by whole periods of the color line to the drawn side. When no
circle is drawn, nothing is painted.
The untranslated report listed 167 status and error messages that none
of the 23 complete-message catalogs translates. The Ukrainian catalog
now has an @msg row for 114 of them: the errors of the image encoders,
color profiles, swatch exchange files and color books, 3D and Revolve,
path operations, DXF import, the script engine and the parameter
checks. Placeholders, backticked names, accepted values and limits stay
as the English writes them. Open #7211, #7378 and #7405 translate the
other 53.
A gradient stop that loses its link to a spot swatch kept the process
plates it printed with that ink, so it carried a DeviceN mix with no
ink. Paint::map_links, which deleting a swatch, recoloring and color
adjustments go through, now clears a stop's plates whenever it leaves
the stop without a link, as GradientStop::set_color(color, None)
already does. Library gradients and library character styles linked
to a swatch the document lacks unlink their stops the same way.
Docs: docs/target-app-parity.md.
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.