The styles were stored on the text and written to SVG's text-decoration,
but the type was drawn without the lines. vectorcraft_text::decorations
now gives each underlined or struck-through stretch of a run on a line
its bar, placed and sized from the font's own underline and strikeout
metrics (with fallbacks for fonts that have none). The canvas, Create
Outlines, PDF export (outlined and real text) and SVG's outlined text
draw them in the run's paint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
swatch.library.copyToUser {library} copies a library loaded from
another folder into the user library folder of the desktop app. A
.vcswatches, .gpl or .ase file is copied as it is; the swatches of a
document and a library loaded from the data or dataBase64 parameter are
written as a .vcswatches file. The copy gets a name that no file in the
folder has, and when a file with the same extension and bytes is
already there, that file is used. The library is then listed as User
Defined only. Until the app quits, commands given its loaded id use the
copy, unless another library is loaded under that id. Without a user
library folder (the web and headless sessions) the command is disabled.
A file with the same extension and bytes as a User Defined library
opens as that User Defined library. The unchanged original of a copied
.ase file is one such file. Graphic style libraries open the same way.
An ellipse kept pie angles in its model, but nothing drew or set them. Now
the Transform and Properties panels show Ellipse Properties with Pie Start
Angle, Pie End Angle and Invert Pie, as in Illustrator, and
object.setLiveShape takes {pieStart, pieEnd, invertPie}. The pie runs
counterclockwise on screen from the start angle (0 at 3 o'clock) to the
end angle and closes through the centre; 0 to 360 is the whole ellipse,
an end of 0 means 360, and Invert Pie swaps the angles to show the other
part. One undo step each; a bad angle is an error. The labels are
translated in every complete language. The on-canvas pie widget is still
to come.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A font library can hold two versions of one family and style (a new
Montserrat-Bold.ttf beside an old montserrat.ttf). The font database kept
only the first one loaded, so type set in the other couldn't be matched
when a PDF or .ai was opened: it came in as outlines. Now every version
loads (the first stays the one family and style resolve to), PDF import
tries the other versions when the glyphs differ, and type set in a version
the family and style alone wouldn't pick names it in CharStyle::font_version
(left out when None, so documents without it are unchanged). Layout,
shaping, the substituted-glyph highlight, Find Font, Package and Document
Info follow it; changing the font clears it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As in Illustrator, the Pen shows its continue cursor over an end of any
open path, selected or not, and a click there selects the path and draws
on from that end (reversing it from its first end). While drawing, it
shows a join cursor over an end of another open path, and a click joins
the two into one path, in one undo step, which finishes the path.
path.join takes {ids: [a, b], ends: ["first"|"last", "first"|"last"]}
to join the ends asked for (the Pen's join); without them it joins the
selected paths' nearest ends as before. Joining a path with itself, or
anything that isn't a path, is an error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File › Package and Document Info › Font Details looked fonts up with
FontDb::face and compared the face's family with the name the document
stores. A font a document named by another of its names (a PostScript
or localized name, as SVG and PDF files do) was reported as not
available and left out of the package, although the canvas drew it and
exports embedded it.
- Package and Font Details resolve fonts with FontDb::resolve, as
text.fonts and the renderer do. A style the family lacks is still
copied as its closest style; the report now names the style it
copies, and Font Details lists the font as substituted, with that
style's file and permission.
- FontFace::embeddable reads fsType as exports do (Embedding), so fonts
that allow bitmap embedding only (bit 9), or that set the restricted
bit together with reserved bit 0 (0x0003), are no longer copied.
Document Info's permission labels follow the same rule: when a font
sets more than one usage bit, the label names the most permissive
one.
- The Package dialog and its status line name the fonts it didn't copy.
The Save Swatch Library dialog lists Swatch Exchange (.ase) as a
format, and swatch.library.save takes format: "ase" or a path ending
in .ase. Each solid color keeps its model (RGB, CMYK, Lab or Gray) and
its type (spot, global or process), and color groups stay groups.
Gradients and patterns are left out, and a tint swatch is written as
the color it shows. Without a path or user: true, the command returns
the file as dataBase64.
A swatch exchange library opens under the name of its file. When Save
Swatch Library or Save Graphic Style Library saves to a file, the save
panel suggests the Name from the dialog as the file name, as a save to
User Defined does, and the web app downloads the file under that name.
A name made only of dots and spaces, such as "...", gives the file name
Library (Library.vcswatches) in place of a hidden file.
palette_io::write returns the file's bytes. A property test writes
generated libraries and reads them back, and an import fuzz test loads
mutated copies of a file the writer wrote.
Clippy 1.99.0 added `chunks_exact_to_as_chunks`, which fails `cargo xtask ci`
at its clippy step. Eight uses of `chunks_exact(_mut)` with a constant size now
use `as_chunks(_mut)` (stable since 1.88, within the 1.95 minimum): four in
crates/affinity, three in crates/effects and crates/engine tests, and two in
xtask's sha256. docs/development.md says the gate targets the current stable.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Libraries panel was a placeholder: it invited dragging art onto it,
but nothing happened. It now keeps local libraries (no account, no
cloud), as Illustrator's Libraries panel does:
- drag art off the canvas (or a swatch) onto the panel to add it, or use
+ to add the selection's graphic, fill or stroke colour, character
style or paragraph style;
- drag a graphic onto the canvas (or double-click it) to place a copy,
click a colour to paint the selection through the active Fill/Stroke
proxy, click a style to apply it to the selected type;
- the library picker and the panel menu create, rename and delete
libraries; each is a .vclibrary file in a Libraries folder next to the
preferences (session-only in the web app, headless sessions and runs
without preferences).
Engine: library.list/get/setCurrent/create/rename/delete/add/use/
removeItem. A graphic is stored as a native document with a thumbnail:
adding copies as Copy does and placing pastes as Paste does, resources
and swatch-name conflicts included. Using a style adds it to the
document and applies it in one undo step.
Clipboard::to_document gave its layer the id u64::MAX, which made a
saved copy overflow Document::fix_next_id when read back; the layer now
takes an id above the objects', and fix_next_id saturates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PDF writer defaulted to Convert Text to Outlines, so every glyph of
every page became a path: a text-heavy PDF grew several times larger on
export (a 7-page document went from 27 KB to 226 KB) and its text could
no longer be selected or searched. Illustrator's PDF presets embed font
subsets and keep live text; that is now the default too
(advanced.outlineText: false). Outlining stays available as an option,
fonts that can't be embedded still become outlines with a warning, and
printer's marks (page information) are drawn as shapes as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`artboard.setProps {scaleArt: true}` maps the art fully inside a resized
artboard (as Move Artwork with Artboard gathers it) and its artboard guides
from the old rectangle onto the new one, each side by its own ratio, in one
undo step, and returns the ids scaled. Strokes, effects and corners follow
Scale Strokes & Effects and Scale Corners (`strokes`, `corners`), pattern tiles
Transform Pattern Tiles (`patterns`); locked and hidden art follows
`lockedAndHidden` (default: prefs moveLockedWithArtboard). The resolved choices
are journaled, so a replay scales the same objects the same way. A move that
keeps the size scales nothing.
The Artboard tool's `scaleArt` option (saved with `moveArt`) makes handle
drags proportional, as the public help describes, keeps them proportional at
the 1 pt minimum, and leaves the scaled art out of the Smart Guide targets.
Move and Scale Artwork with Artboard are check boxes in the Control bar and
Properties' Edit Artboards; the artboard size fields there and in the
Transform panel pass the option. Translated in the eight catalogs that have
Move Artwork with Artboard. docs/mcp.md and the ROADMAP updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
During a Selection-tool drag the bounding box and its handles stayed on
screen while the art moved, so the content looked as if it slid inside
a box of its own. The box now hides once a drag moves, scales or
rotates the selection, as in Illustrator, and comes back on release. A
press that hasn't moved, and a marquee, keep it. Tools gain
`transforming()` (Session::tool_transforming) for this.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Such a file's PDF part is a placeholder page, which was refused. When
the file carries editing data, it now opens from that alone: its
structure as a PDF-compatible file's, its point type made from the text
document, and type it can't make (area type, type on a path) left out
with a note that marks the import as lossy. Without editing data, or
with pages picked or layers off, the placeholder is refused as before;
damaged editing data says so.
The page-order note is no longer given when the page has no type.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The layers reader of the editing copy (operators translated into
PostScript for the interpreter, any file with RGB colours, gradients,
transparency or images falling back to its page) is replaced by a reader
of the whole structure (import/ai): layers and sublayers with their
options, groups, compound paths, clipping groups and layer clipping,
names, hidden and locked objects, RGB, CMYK, grey, named and spot
colours, gradients, transparency, fill rule, overprint, embedded images
with their alpha channel, guides and every artboard, and objects drawn
as their look when they have several fills or strokes, effects or a
brush. Containers: Zstandard, zlib or plain data in EPS and .ai.
The text placement, the comparison with the page and the overwrite guard
stay around it. The page's type takes its text object's place without a
group; the comparison is by lightness, on nothing, without layers that
don't print. Symbols, pattern fills, placed files and unknown operators
make the file come in as its page where they show, and are left out of
layers that don't.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paragraph panel › Kinsoku Set (with the East Asian options) and `text.setFormat {kinsoku}`, as
decided in #633:
- Hard: today's set, so existing documents don't change; the default, and not saved.
- Soft: as Hard, except that 々, the prolonged sound mark ー (JLREQ cl-10) and small kana (cl-11)
may start a line: JLREQ's level 3 line-breaking rules (Appendix C.3). Half-width forms aren't in
those classes and stay off the line start.
- None: no kinsoku.
The setting reaches every break the composers consider (greedy, every-line and hyphenation
points). Reset Panel returns to Hard.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The engine refuses to write over the file a document was read from when
reading it left something out, unless acknowledgeLoss is passed. In the
app that surfaced as an error naming a parameter. File > Save, Save As,
Save a Copy, Save as Template and Export As now ask instead ("Replace
'a.eps', the file this document was opened from?", with what would be
lost), and OK repeats the command with acknowledgeLoss. Closing a
document whose save asks keeps it open, and so does Package.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>