uk is in COMPLETE_MESSAGES, but the untranslated report listed status
and error messages with no Ukrainian row, so with the interface in
Ukrainian those messages showed in English.
- uk.tsv gains 1,811 `@msg` rows. The translations are VectorCraft's
own, written from the English meaning with the catalog's terms and
typography (« » around interface names, ’ inside words).
Placeholders, backticked names, command ids, double-quoted values and
bare true, false and null stay as the English writes them.
- The 41 rows that open #7211, #7214, #7116, #7330 and #817 add to
uk.tsv are left out, so the catalog keeps one row per key when they
merge (bundled_catalogs_are_consistent rejects a second row for a
key).
- The Ukrainian row of docs/localization-parity.md gives the catalog's
counts.
When a read document is brought within the canvas, each saved guide was
checked against the removed artboard ids and the removed layer ids with
linear scans, and each guide node against the removed artboard ids, so
the work grew with the number of guides times the number of removed ids.
The ids are now collected into ordered sets, and each guide is checked
in logarithmic time.
Removing what lies beyond the canvas scanned each container's whole
subtree to see whether anything reached beyond, then scanned each child
again while removing, one level down at a time, so a deeply nested
object was measured once for every group around it. Removing guide nodes
probed each layer's subtree the same way before descending into its
sublayers. Both now make one read-only walk that records, by index,
which objects reach beyond (or which guides are removed), and the
removal follows that record. The objects clipped by a clipping path
beyond the canvas are still not measured.
Containers with nothing to remove are still not copied. The objects and
guides that remain, their order, the counts, the retired artboard ids
and the saved selections are unchanged.
Right-to-left type on a path that overflows searched for the start of its
text that fits with a binary search, which assumed that a longer start
never fits once a shorter one does not. A letter tracked to a negative
advance breaks that: with steps of 6, 6, -3 and 6 points in a 10 point
span, the first three letters fit while the first two do not, and the
search showed only the first letter.
- Without hanging punctuation, and with no spacing or on a path of one
straight segment, every start is measured in O(n log n): each glyph
keeps its place in the whole text's visual order, except the trailing
whitespace and controls that UAX #9 rule L1 sets to the paragraph's
level.
- With hanging punctuation, or spacing on a curve, when a letter has a
negative advance, a start is a candidate only when its glyphs, in its
own visual order and each at the least step it can take, reach no
farther than the path's length. This lower bound holds with negative
advances.
- At most 32 candidates are arranged from the longest. When none of
them fits, a binary search over the rest shows a start that fits,
which is not always the longest.
- With hanging punctuation, or spacing on a curve, text with no negative
advance keeps the binary search.
Right-aligned and centered type on a curve with Spacing was placed using
the width its glyphs have at the start bracket, while the steps were
measured where the line was placed, so a line that fits could end past
the end bracket and lose glyphs. It is now placed using the width of the
steps it has where it is placed.
A path directly in a graph series lost what these commands gave it when
the graph was drawn again, for example after graph.setData:
- While Global Edit is on in an isolated graph, a match that is a series
path, or a series group whose paths take the edit, now has what
changed on its paths stored for their series: the paint, weight,
opacity and blend mode of the topmost visible fill and stroke, and the
object's opacity and blend mode. The edited match is stored by its own
command as before.
- addon.arrange.randomizeOpacity and addon.arrange.sort with apply
"opacity" now store the object opacity, with the blend mode, of the
series paths whose opacity they change. When they change several
paths of one series, the frontmost of them sets what the graph
stores, as for the other commands.
The graph stores them in the same undo step as the edit. The params
text of addon.arrange.randomizeOpacity and addon.arrange.sort,
docs/mcp.md and docs/target-app-parity.md describe the new behavior.
The check after each edit that the selected objects stay within the
canvas measured the whole of every selected path. Moving one anchor of
a 10,000-anchor path measured all 9,999 segments. A path or compound
path whose anchors and handles are all finite and inside the canvas
range now passes without being measured, because its curves stay inside
their control points. A path with a point outside that range is still
measured, so the check accepts and refuses the same edits as before.
path.moveAnchor to the point the anchor is already at, and
path.setHandle to the point the handle is already at, now leave the
document as it is and record no undo step.
vectorcraft_geom::path::measured_segments counts the segments that
PathData::bounds measures, and the new engine tests use it.
A 3D effect on a fill or stroke worked on copies of the object's fills
and strokes, and the copies were looked up among the object's items by
identity, so a live-effect plug-in before that 3D effect was given
`_context.item` "object" and a deferred stage there was listed with no
item. The drawn art, the 3D meshes and Expand as Wireframes now pass the
original item, so the plug-in is given `{"fill": i}` or `{"stroke": i}`
as docs/plugins.md describes. The paints of a type's first run still have
no item.