Commit Graph
2929 Commits
Author SHA1 Message Date
Elias Witt f5c3ecb47c Path: Smart Remove Anchor Points is a menu command
path.smartRemoveAnchor stays. Object › Path, the Control bar, the contextual task bar, Properties, and the canvas context menu run it on direct-selected anchors. The Pen no longer uses Alt/Option for this, so that key stays free for Convert Anchor Point.
2026-10-08 03:25:44 +07:00
a1f2f23b72 Direct Selection: handle snapping ignores the path's moving bounds, Shift follows the Constrain Angle (review of #332)
- A dragged handle no longer snaps to its own path's bounds and centre, which move with the
  handle; the path's anchors are point and alignment targets instead.
- Shift steps 45° from the Constrain Angle preference, like the cut and gradient tools.
- snap_draw and snap_handle share one pixel/grid/smart-guides switch.
- A test that a smooth anchor's opposite handle turns with a Shift-dragged handle and that Alt
  still breaks it, and the tools' module docs (both from #338).

Co-authored-by: theironchef <6278036+theironchef@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:25:27 +07:00
EthanSuquetandClaude Opus 5.5 86de124cc8 Fix #322: dragged direction handles take Shift and smart guides
Dragging a direction handle with Direct Selection or the Anchor Point tool
sent the pointer position straight to path.setHandle: Shift did nothing and
the handle never snapped, while the Pen already constrains the handles it
pulls out.

guides::snap_handle places a dragged handle: with Shift at a multiple of
45° from its anchor (the Pen's constraint, keeping the dragged length),
otherwise snapped as a drawn point is (smart guides, the grid, pixels).
Both tools use it and show the smart guides while the handle moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:25:27 +07:00
bflatasticandClaude Opus 5.5 820f405c61 Dialogs: note first-field focus in the ROADMAP (review of #308)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:23:11 +07:00
theironchefandClaude Opus 5.5 aa9e2e89c8 Fix #307: a form dialog opens with its first field focused
Rotate, Scale, Move and the other form dialogs opened with no field
focused, so a typed value went nowhere and Enter applied the default (a
Rotate by 0 degrees). The frame a dialog opens on (after the window's
measuring frame), its first text or number field takes the keyboard
focus with its text selected, so typing replaces it and Enter applies
it, as in the reference app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:51 +07:00
bflatasticandClaude Opus 5.5 5e0c911633 Brushes: a brush dropped on a compound path's part applies to the compound (review of #298)
Use the paint owner, as a dropped swatch does. The Asset Export panel's drop zone uses
the shared art_drop too. Note the new drag and drop in the ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
bflatasticandClaude Opus 5.5 17e654a738 Artboard tool: share the artboard copy with Duplicate Artboard, report the copies (review of #348)
artboard.move with copy and artboard.duplicate now make the copy with one helper: a
new id that can't overflow and a name of its own (`<name> copy`, then `<name> copy 2`…,
so two copies of one artboard no longer share a name). `moved` lists the copies a copy
moved rather than the originals it left. Test it with and without moveArt, and note
Alt-drag in the ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
bflatasticandClaude Opus 5.5 3b2376af9c Artboards: one active artboard for the panel, the navigator and the Artboard tool (review of #351)
As in Illustrator, double-clicking an artboard's number goes to it (fits it in the
window) and double-clicking the name renames it. A row's Options button chooses the
Artboard tool on that row's artboard, clicking a row moves the Artboard tool to it
while it is chosen, and an artboard clicked with the Artboard tool becomes the active
one the panel highlights. Note it in the ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
bflatasticandClaude Opus 5.5 c074a8031f Layers: Alt-click an eye or lock runs Hide/Lock Others and Show/Unlock All (review of #301)
Illustrator's Alt-click on a layer's eye hides the other layers and, once they are
hidden, shows every layer again; the lock column does the same with Lock Others and
Unlock All Layers. Reuse the panel menu's commands (one undo step each, named as the
menu items) instead of toggling the row's siblings, so a sublayer's or an object's row
stands for its top-level layer. Document it in the ROADMAP and docs/mcp.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
bflatasticandClaude Opus 5.5 ad8c31b3af Layers: one next_layer_name, in the document (review of #341)
The engine kept its own copy of Document::next_layer_name after #353; the
document's now counts sublayers too, so the engine uses it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
theironchefandClaude Opus 5.5 7830a41b3e Fix #297: the Swatches and Brushes panels take drag and drop
Art dragged off the canvas and released over the Swatches panel becomes
a pattern swatch of a copy of it (object.pattern.make without entering
pattern editing; the art stays), and over the Brushes panel an Art brush
(brush.new, as the panel's New Brush button makes). A brush dragged out
of the Brushes panel (PanelDrag::Brush, with a preview chip) is applied
to the path it is dropped on (brush.apply). The art drop zone helper
moves to widgets, shared with the Symbols panel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
theironchefandClaude Opus 5.5 41c7495844 Fix #346: Artboard tool: Alt-drag duplicates the artboard
Alt-dragging an artboard moved it like a plain drag. artboard.move now
takes copy: it leaves the artboard (and the art it carries) where it
is and moves a copy, named "<name> copy", with copies of that art. The
Artboard tool previews it while Alt is held, as "Duplicate Artboard"
(Alt pressed or released mid-drag switches between copy and move),
and makes the copy the active artboard, as in the reference app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
theironchefandClaude Opus 5.5 a54be8298f Fix #349: clicking an artboard in the Artboards panel makes it active
The panel kept its own selection (a pstate nothing else read), so a
click only highlighted the row: the status bar navigator, Fit Artboard
in Window and Actual Size stayed on the previous artboard. The panel's
selection is now the view's active artboard (View::artboard): a click,
Move Up/Down and New Artboard set it, and the highlight follows the
navigator, per document, as in the reference app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
theironchefandClaude Opus 5.5 59212cb0d4 Fix #299: Alt-clicking a layer's eye or lock toggles the others
In the Layers panel an Alt-click on an eye or lock now applies to the
other items beside that row (the other layers for a layer) in one
object.setProps step: it hides or locks them while any of them is shown
or unlocked, else shows or unlocks them all, as in the reference app. A
plain click still toggles only that row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
theironchefandClaude Opus 5.5 6d1d94bf11 Fix #340: new layers and sublayers share one "Layer N" numbering
A new sublayer was named "Layer {node_count}", counting every object, so
an empty document's first sublayer was "Layer 1" like its parent and a
document with five objects got "Layer 6". Top-level layers counted only
top-level names and could repeat a sublayer's. Document::next_layer_name
now counts every layer, sublayers included, and skips any layer's name;
layer.newSublayer uses it too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:50 +07:00
bflatasticandClaude Opus 5.5 3cd2fddeda Shape tools: Space moves Arc, Spiral and the grids too, through one helper (review of #304)
The Line Segment family (Arc, Spiral, Rectangular Grid, Polar Grid)
ignored Space while drawing, as the shape tools did before #302. Both
tools now share shape::space_moves. A headless canvas test presses Space
for real in the middle of a Rectangle and a Pen drag: the shape and the
anchor move and the view doesn't pan. Adds the ROADMAP entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:32 +07:00
bflatasticandClaude Opus 5.5 7feeb73a81 Pen: Auto Add/Delete reuses the Add/Delete Anchor Point tools' hit tests (review of #312)
The Pen's Auto Add/Delete had its own copy of the anchor and segment hit
tests and of the path.insertAnchor / path.removeAnchor actions the Add
and Delete Anchor Point tools build. draw2 now exposes anchor_in /
segment_in (the hit tests over a given set of paths) and insert_anchor /
remove_anchor, which both tools use. Adds the ROADMAP entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
bflatasticandClaude Opus 5.5 0830ad68c3 Pen: ROADMAP entry for clicking the last anchor (review of #330)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
bflatasticandClaude Opus 5.5 c322f24086 Pen: ROADMAP entry for Space moving the anchor being placed (review of #315)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
bflatasticandClaude Opus 5.5 464a93c7f9 Pen: ROADMAP entry for Alt pressed mid-drag (review of #310)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
theironchefandClaude Opus 5.5 736a1bde25 Fix #302: holding Space while drawing a shape moves it
The shape tools (Rectangle, Rounded Rectangle, Ellipse, Polygon, Star,
Line Segment) ignored Space during a drag. While Space is held once the
drag has begun, the drag's start now moves with the pointer, so the
shape being drawn moves at its current size; letting go of Space resumes
sizing from there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
theironchefandClaude Opus 5.5 133390ef7a Fix #311: Pen: Auto Add/Delete on a selected path
Between paths, the Pen now adds an anchor where a click lands on a
segment of a selected path and deletes the anchor a click lands on,
with the add and delete cursors while hovering, as in the reference
app. The ends of a selected open path still continue it. Shift held,
or General > Disable Auto Add/Delete (a stored preference nothing read
until now, passed to tools as ToolContext::auto_add_delete), starts a
new path instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
theironchefandClaude Opus 5.5 1b3a03316e Fix #314: Pen: clicking the last anchor retracts its handle
While drawing, a click on the last anchor appended a second anchor at
the same spot, keeping the old outgoing handle, so the path got a
zero-length curve that showed as a spike. Now a click there retracts
the anchor's outgoing handle (the next segment leaves it as a corner)
and a drag pulls a new outgoing handle out on its own, with a convert
cursor (^) over it, as in the reference app. A one-anchor path no
longer closes on itself when its anchor is clicked again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
theironchefandClaude Opus 5.5 0b844a13af Fix #313: Pen: holding Space while dragging out a point moves it
The Pen ignored Space during a drag, so the anchor being placed stayed
where the button went down and its handles swung round it. Space held
now moves the anchor, handles and all, as far as the pointer moves
(the handle Alt kept moves along too); releasing Space goes back to
shaping the handles round the new place, as in the reference app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
theironchefandClaude Opus 5.5 bef928bf17 Fix #309: Pen: Alt pressed mid-drag keeps the curve into the new anchor
Pressing Alt while dragging out a smooth point set its incoming handle to
the anchor itself, so the segment just shaped turned straight. The Pen
now remembers the incoming handle it last previewed and keeps it while
Alt is held, so only the outgoing handle follows the pointer: a corner
with curves on both sides, as in the reference app. Alt held from the
start of the drag still gives an outgoing handle only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:22:31 +07:00
BFlat 5cacbe36b3 Merge pull request #360 from storytold/pr/readme-screenshots
README: refresh the screenshots and renders, add a Perspective Grid shot
2026-10-08 02:42:07 +07:00
bflatasticandClaude Opus 5.5 1c3b7b16db README: refresh the screenshots and renders, add a Perspective Grid shot
- Five app screenshots retaken from the current build at 2240x1400 (UI at
  1.6x): the hero shows the Outer Glow settings in the Appearance panel, the
  Live Blends shot shows the new Layers panel rows, and a new shot shows a
  two-point Perspective Grid scene (examples/perspective-city.vectorcraft,
  built through the command API).
- "A look around" is a 2x2 grid; captions and alt texts follow the shots.
- The "Made in VectorCraft" art is re-rendered with vectorcraft-cli (the
  radial Repeat's gradients now turn with each instance).
- Every image is losslessly optimised with oxipng (7.2 MB -> 4.4 MB,
  pixel-identical).
- ASSETS.md rows for the new screenshot and example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 02:39:29 +07:00
Fabian GrajalesandClaude Opus 5.5 3bc4365ee2 Smart Guides: a turned bounding box snaps while it is resized
The resize snap skipped a bounding box standing at an angle. It now works
on the page whatever the angle: a corner handle takes the target's x, y or
both, and a side handle (or a proportional corner) slides along its own
direction until the handle or an end of its side is on a target. A target
the side runs almost along is skipped, so the handle stays near the pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013j16ENkbsNYyHSCDhxYkYR
2026-10-07 14:32:11 -05:00
Brandon ThomasandClaude Opus 5.5 1f7873273b Rename PrintCraft to PdfCraft (storytold/pdfcraft) (#356)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:45:57 -04:00
haven 364c579c04 M11: artboards snap by their bleed; transform panel edits an active artboard 2026-10-07 11:42:00 -07:00
haven 9cd91deafa M11: Artboard tool snaps artboards while moving and resizing 2026-10-07 11:41:33 -07:00
Fabian GrajalesandClaude Opus 5.5 7de04544e4 Smart Guides: bounding-box resizes snap to the other objects
Dragging a bounding-box handle with the Selection or Free Transform tool
now lands the edges it moves on the edges and centres of the other objects
and artboards, with the guide line, as a move already did. A proportional
scale snaps the closer axis only; a turned bounding box doesn't snap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013j16ENkbsNYyHSCDhxYkYR
2026-10-07 13:05:37 -05:00
BFlat 65c5953516 Merge pull request #353 from storytold/feat/layers-panel
Layers: the whole Layers panel, with sublayers, groups and objects as clickable rows
2026-10-07 23:49:12 +07:00
BFlatandClaude Opus 5.5 0648e99fc4 Layers: keep clippy happy (menu item type, no unreachable in tests)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:06:31 +07:00
BFlatandClaude Opus 5.5 ccdb4d89c1 Layers: the panel's rows work in the collapsed dock's flyout
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:54:34 +07:00
imachusandClaude Opus 5.5 a92905a816 Type: mojikumi — Line-end Punctuation Half Width for Japanese punctuation
Japanese full-width punctuation is half a mark and half a space (an
opening bracket's space before it; a closing bracket's, comma's or full
stop's after it). Set solid, 」「 or 。」 show a full em of air between
the marks, and a line ending in 。 stops half an em short of the edge.

- `ParaStyle.mojikumi` (Paragraph panel › Mojikumi): None, or Line-end
  Punctuation Half Width, which (JLREQ 3.1.4) lets consecutive
  punctuation share one half-em space — a closing mark followed by
  punctuation loses the space after it, an opening bracket after another
  the space before it — and sets a closing mark ending a line half
  width. Only full-width marks (advance an em) are touched, never inside
  a tate-chu-yoko block; vertical type the same way down the column.
- New type (`text.create`, Area/Path Type) takes Line-end Punctuation
  Half Width, the usual default of Japanese layout; documents from
  before it and imported text keep None (written only when set, so
  older files and older apps are unaffected). `text.setFormat
  {mojikumi: "none"|"lineEndHalf"}`.
- Builds on #344: on justified lines the room it frees is spread
  between the characters.
- Catalog rows in ja and zh-hant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 00:46:07 +09:00
Fahri Meral 6f54843d5a Merge upstream/main: keep panel normalization alongside dock collapse behavior 2026-10-07 18:44:42 +03:00
BFlatandClaude Opus 5.5 f8e3cfbf35 Layers: document the Layers panel commands and update the ROADMAP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:29:15 +07:00
BFlatandClaude Opus 5.5 7eb3f25f1f Layers: sublayers, groups and objects are clickable rows in the panel
Rows at every depth highlight on click (Shift range, Ctrl toggle) and make
their layer current; selection squares select a row's art and drag the
selection to another row; eye and lock on every row with drag-down-the-column
in one undo step and Ctrl-click for Outline; Alt-click triangles; drag and drop
rows above, below or into layers and groups with a drop line (Alt copies);
Delete key; the full panel menu, Layer Options and Panel Options dialogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:29:15 +07:00
BFlatandClaude Opus 5.5 27a1a48176 Layers: sublayers are layers, not objects, and every row has a command
Art in a sublayer is now selected as objects (clicks, marquee, Select All, the
Select menu), sublayers select in their own colour, and hidden, locked or
template sublayers block clicks. Layer Options gain Preview (per-layer outline)
and Dim Images. New and fixed layer.* commands for the Layers panel: setCurrent
and highlight (rows at any depth), selectAll, move (reparent with cycle and
nesting checks, Alt copies), delete/duplicate rows, merge, flatten, collect,
release to layers, reverse, template, hide/outline/lock others and their
show/preview/unlock all, locate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:29:15 +07:00
BFlat f9209e8896 Merge pull request #347 from storytold/fix/issue-293
Fix #293: the dock's double arrow collapses its panels to icons
2026-10-07 22:27:32 +07:00
BFlatandClaude Opus 5.5 f16403a851 Fix #293: the dock's double arrow collapses its panels to icons
The » at the top of the right dock was only painted. Its header strip is
now a click target (hover highlight, "Collapse to Icons" tooltip) that
runs the new window.collapseDock UI command: the Properties | Layers |
Libraries group hides and its three panels become icons at the top of
the icon column, under a « strip ("Expand Panels") that expands them
again. While collapsed, those icons and window.panel pop the panel out
next to the column like the other icon panels (dock-width flyout, Layers
and Properties given a height that keeps them on screen); expanding with
one popped out shows its tab.

The flyout now follows the icon column's real left edge (recorded each
frame) instead of assuming a 300-point dock, so it also tracks a resized
or collapsed dock. The collapsed state is kept with the UI preferences
and in user workspaces; the built-in workspaces expand the dock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:21:59 +07:00
imachusandClaude Opus 5.5 5623f90ef7 Type: justified Japanese lines spread between their characters
Justify (last line left, centred or right) widened only word spaces, so
a Japanese line, which has none, stayed set solid and the right edge of
a justified Japanese paragraph was ragged by up to almost a character
(only Justify All spread the characters). Following JLREQ 3.8, the room
left on a line now goes to the gaps next to a CJK character, shared
with any word spaces:

- not inside a Latin word or a tate-chu-yoko block, nor next to a tab;
- lines without CJK characters are justified as before;
- vertical type too (the same code, in line space).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 00:20:18 +09:00
imachusandClaude Opus 5.5 681d18a08f Type: vertical type takes upright glyphs' cells from the font's vertical metrics
Upright glyphs in vertical type advanced one em (or their horizontal
advance, if wider) and turned about a fixed point 0.38 em above the
baseline. Fonts that carry vertical metrics now place them as they ask:

- `FontFace::vertical_glyph`: a glyph's advance down the column (`vmtx`)
  and the height of its vertical origin (`VORG`, else the glyph's top
  plus its top side bearing, as in TrueType fonts); `None` without
  `vhea`/`vmtx` or with values outside a few ems.
  `FontFace::ideographic_centre`: the em box centre from an ideograph's
  cell, else 0.38.
- The layout advances an upright glyph by its vertical advance and hangs
  it from its vertical origin; tate-chu-yoko blocks and point type's
  anchor use the font's em box centre. Fonts without vertical metrics
  are laid out exactly as before.
- Hiragino's tables give the values the layout assumed (one em, origin
  0.88 em), so Japanese vertical type in it renders pixel for pixel the
  same; this is the base for proportional vertical metrics (`vpal`) and
  for fonts whose em box sits elsewhere.
- `test_fonts::vertical_font`: Source Sans 3 with `vhea`/`vmtx` (and
  optionally `VORG`) built in code, one glyph 1.4 em tall hanging from
  1.1 em; tested with and without `VORG`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 00:12:44 +09:00
imachusandClaude Opus 5.5 52e1c0eca0 Type: a font menu with samples, live preview, script and kind filters, styles and favourites
The Character and Properties panels' font menu was a plain searchable
list of names. With hundreds of installed families (and Japanese names
that say little to someone who can't read them) a name isn't enough.

- Each row shows the family's name and a sample of the selected text set
  in it (a generic sample when the font lacks its characters). Samples
  are rendered off the UI thread, a few per frame, and only for the rows
  in view (the list is virtualised).
- The row under the pointer or reached with ↑/↓ previews its font on the
  selected text, as one live interaction with nothing in the history; a
  click or Enter applies it as one step, Escape or closing the menu puts
  the text back. The current family is highlighted and scrolled into
  view, also when the document names it in another language.
- Filters by script (Japanese, Latin) and kind (serif/Mincho, sans
  serif/Gothic, rounded, script/brush, monospaced, decorative), from the
  font's OS/2 classification and, for CJK fonts whose tables seldom say,
  its names. `FontTraits`/`FontClass` in the text crate; installed
  families get them from the same scan as their names.
- ▸ (or →/←) lists a family's styles; a style row previews and applies
  that style.
- ☆ stars a family; the ★ filter shows only the favourites (kept with
  the UI state).
- Preferences › Type › Enable in-menu font previews and Font Preview
  Size now turn the samples off and size the rows; the in-window Type ›
  Font menu (Windows, Linux) shows a sample beside each name.
- Families whose name starts with a dot (the system's own) are hidden.
- Catalog rows for the new labels in zh-hant (complete) and ja.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:51:33 +09:00
imachusandClaude Opus 5.5 fcaeaa74a7 PDF/.ai import: Japanese text as live type (CID fonts, vertical columns, missing fonts)
Japanese PDFs and PDF-compatible .ai files often set text in CID fonts
with no ToUnicode map, in vertical columns, and in fonts the reader
doesn't have. They came in as outlines (or as the wrong characters).

- CID fonts without ToUnicode: the character comes from the font's CFF
  charset through the standard CMaps (hayro's `embed-cmaps`); Kangxi
  radicals that some generators map to are unified with their ideographs
  (⿓ → 龍).
- A glyph becomes live type only when the installed font draws the same
  glyph: compared by box with the font of the PDF's PostScript name, or
  the closest style of its family (a variable font's named instances),
  whose style the type then takes. Otherwise it keeps its outline.
- Vertical columns (WMode 1, glyphs with no horizontal advance) come back
  as vertical type, letter spacing as tracking; a single upright glyph is
  vertical type too. Horizontal lines get tracking from the glyph
  positions the same way.
- Text in a font that isn't installed keeps its outlines (what prints),
  with an editable copy in a substitute font, drawn pink, on a
  non-printing layer named after the missing fonts (stroke-only glyphs
  included).
- Marked content other than a layer's (spans with actual text,
  artifacts) no longer ends a line of type: 篳篥・龍笛・笙 came back as
  three objects when one character was in a span.
- Tests in tests_live_text.rs and tests_realtext.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:45:31 +09:00
BFlat b64dcc02df Merge pull request #329 from storytold/fix/issue-306
Fix #306: render on the power-saving GPU by default, with a preference for the discrete one
2026-10-07 21:21:15 +07:00
BFlatandClaude Opus 5.5 406c27ebd8 Fix #306: render on the power-saving GPU by default, with a preference for the discrete one
On hybrid-graphics laptops (an integrated GPU driving the display plus a
discrete one), egui-wgpu's default power preference is HighPerformance, so
VectorCraft rendered on the discrete GPU and its frames were copied to the
display through the integrated one. On an Asus ZenBook with Intel Iris + Arc
the window flickered whenever the mouse moved over it (#306, #305).

The canvas is rasterized on the CPU (vello_cpu) and the GPU only composites
the canvas texture and draws the UI, so the integrated GPU is plenty. The
desktop app now asks wgpu for the power-saving adapter by default.
Single-GPU machines are unaffected.

- Preferences > Performance > Graphics Processor (`gpuPreference`:
  powerSaving, the default, or highPerformance), with a note that it
  applies after a restart. The app reads it from the saved preferences
  before the window opens. WGPU_POWER_PREF still overrides it.
- Help > About and `ui.inspect` (`graphicsAdapter`) name the adapter in
  use, and it is logged at startup, for future GPU bug reports.
- Docs (README, docs/development.md) and ROADMAP updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:10:17 +07:00
BFlat dfe7f1a311 Merge pull request #326 from storytold/fix/issue-296
Fix #296: variable fonts list and draw every named style
2026-10-07 21:09:48 +07:00
EthanSuquetandClaude Opus 5.5 7e0ed6b183 EPS import: EPS files from the reference app open as vectors
#249 made the reduced repros of #234 open, but a real file saved by the
reference app (version 30) still fell back to its screen-resolution preview
with "typecheck in `a dictionary`". Running its prolog to the end needed:

- The standard dictionaries (systemdict, userdict, globaldict, statusdict,
  errordict, $error) as values in systemdict, so `/globaldict where
  { /globaldict get begin } if` gets a dictionary, not an operator.
  SharedFontDirectory names the font directory too. errordict has a
  handleerror for prologs that wrap it.
- `dictstack`, `internaldict`, `currentsystemparams` and
  `currentuserparams` (with the cache sizes programs `get`), and `cshow`.
- Executable files: `cvx` and `cvlit` set a file's attribute, `xcheck`
  reads it, and executing one runs its data as a program, as the prolog
  does with `(...) 0 () /SubFileDecode filter cvx exec`.
- SubFileDecode with a count of 0 and an empty end string passes its
  whole source through instead of nothing.
- `flushfile` on a filter over the program's data skips that data (the
  file's XMP packet). A filter chained from a pending one leaves it
  nothing to skip, so the writer's own `VCsrc flushfile` is unchanged.

The interpreter empties its standard dictionaries when it finishes, since
systemdict now holds itself. Both real files tested now import as 15
vector paths in CMYK with no warnings, and round-trip through SVG and PDF
pixel for pixel. The EPS fuzzer exercises the new operators.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:06:56 -04:00