A drag or release within a pixel of the last stroke point now gives
that point the pen's tilt and rotation, so the outline and the erased
area follow a pen turned or tilted in place. A release without a pen
reading keeps the last pose. The outline's size on Pressure, Tilt,
Bearing or Rotation goes past 1296 pt, as path.eraseRegion sweeps it.
Eraser Tool Options gives Angle, Roundness and Size each a variation menu
(Fixed, Random, Pressure, Tilt, Bearing, Rotation) and a Variation field.
path.eraseRegion takes angleMode, roundnessMode and sizeMode with their
variations, sweeps a varying tip as a Calligraphic nib with what the pen
read along the drag, and refuses an unknown mode or a variation out of
range. The Eraser records the pen's pressure, tilt and rotation when a
mode follows them, and its tip outline at the pointer takes the angle,
roundness and size the pen gives while it erases.
Type on an open path can now start before the path's start: its start
is stored below 0, the span runs from there, and the characters whose
middle falls before the path's start are not drawn, as SVG 2 lays out
text on a path (https://www.w3.org/TR/SVG2/text.html#TextLayoutPath).
The text keeps every character, and the start bracket stays at the
path's start. Past the path's end, text that does not fit is overflow,
as for other type on a path. Type that starts on the path draws every
glyph as before.
- SVG import keeps a <textPath> start before an open path's start
(text-anchor end or middle, or a negative startOffset) instead of
starting the text at the path's start, which drew every character.
- SVG export writes it as a negative startOffset.
- PDF export writes only the characters drawn on the path.
- The legacy .ai and .ai editing data writers write the type from the
path's start with the type attributes warning.
- type.pathOptions takes a start below 0 for type on an open path; on a
closed path it is the path's start, as before. A flip starts the type
at its start bracket. Dragging the center bracket slides it from where
it starts, and no further before the path.
- A click at the path's start places the caret by the first drawn
character, and the caret in the hidden characters stands at the
path's start. The highlight of substituted fonts and glyphs leaves
them out.
- Release Type on a Path keeps the first drawn glyph where it was
drawn, with the hidden characters before it.
- The Touch Type tool shows no box for a hidden character, and
text.touchType returns an error for one. A character with a drawn
glyph is changed by that glyph.
Docs: docs/mcp.md, docs/target-app-parity.md.
When the third click of a triple-click landed on a face or edge that
the double-click before it had painted (a neighbor the flood or the edge
walk reached), the triple-click sent that part's new paint as match,
since only the clicked part's paint was recorded. The bucket now records
the fill or drawn stroke paint of every other part a double-click
reaches, and a triple-click on one of them matches the paint it had
before the double-click. docs/mcp.md says so.
livePaint.strokeEdge wrote the paint and weight into an edge's topmost
stroke even when that stroke was hidden. An edge whose hidden top stroke
sat over a drawn one kept drawing its old paint, and since the edge
scopes now match the paint an edge draws, a samePaint or connected
stroke reached such edges and changed nothing on screen. The command now
paints the topmost stroke that is shown, and adds a stroke above the
others when every stroke is hidden or there is none. The "nothing
changes" check reads the same stroke.
The doc comments of the scopes and of the press record describe the
drawn stroke paint, and the engine names Paint through its parent module
instead of in the import list. Live Paint Selection's comment on a
triple-click states that the tool takes no action on it.
New tests cover the edge the tool matches on a multi-click over a hidden
or fully transparent edge, the connected edge scope through transparent
and hidden edges, and painting the shown stroke.
Perspective Grid Options gets the two Automatic Plane Positioning
checkboxes, Anchor Point of Perspective Artwork and Intersection of
Gridlines. With the Perspective Selection tool, Shift held over an
anchor point of art in perspective, or over a gridline intersection,
with no button down, moves the active plane through that point and
hides the other planes. A plane made active then passes through the
same point. The plane goes back to its place once an object is drawn
on it or attached to it, when the grid hides or no plane is active,
when the file is opened again, and with Escape.
- perspective.plane.infer {at?, tolerance?, clear?} positions, reads
and clears the held point, which is view state, not an undo step.
- perspective.widget.options takes anchorPoint and gridlineIntersection,
both on by default and kept with the preferences.
- perspective.plane.move moves a held plane from where it is held.
The Live Paint Bucket's connected and samePaint scopes kept their own
copies of the face flood and the edge walk. They read an edge's stored
stroke paint, so an edge that is fully transparent or whose stroke is
hidden stopped a face flood and matched as stroked. The face flood also
required outlines within 0.0001 pt of an edge, which a curved face that
the planar map refits can miss.
The engine now calls the shared flood_faces and connected_edges that
Live Paint Selection uses (#7342), and compares edges by lp_stroke_paint,
the paint of the topmost stroke that draws. The tool records that same
paint as the match for a double-click or triple-click on an edge. The
params text and docs/mcp.md describe the drawn stroke paint.
A visible, unlocked Live Paint face or edge whose own opacity is 0 draws
nothing, as Expand and the edge stroke check already treat it, but the
Shape Builder still took it as an input. It now leaves such faces and
edges out; hidden and locked parts keep their current handling.
main's Live Paint Selection double-click (#7342) replaced the tool's
catch-all pointer arm with an explicit DoubleClick arm, so the
TripleClick kind this branch adds left the match non-exhaustive. The
tool now takes no action on TripleClick: the third click's press and
release already select what a click selects, as before the merge.
The merge also took main's import list in the engine's Live Paint
commands, which no longer named Paint while this branch's Merge code
still uses it; Paint is imported again.
Direct Selection on a dynamic symbol's instance below a layer whose
Preview is off tested and outlined the art in Preview, where the canvas
draws it in outline with the plain clipping paths. When a clipping
path's effects left no region, a selected object in its clip group kept
an outline cut to the plain clipping path.
- `hit::symbol_part_at` and `hit::symbol_part_outline_in_view` count the
layers around the instance, the isolated container and the layers
around it apart, as clicks outside symbols do.
`symbol_part_outline_in_view` takes the click options in place of the
outline flag.
- The outline of an object is empty when the effects of a clipping path
around it leave no region.
Direct Selection on a dynamic symbol's instance picked an object in the
region its clipping path's effects give it, but cut the object's outline
to the plain clipping path, so the outline came out empty or cut short.
In a layer of the art whose Preview is off, it tested the effect-shaped
region and the fills, where the canvas draws the plain clipping path and
outlines.
- `hit::symbol_part_outline` cuts to the bounds of the effect-shaped
region. The new `hit::symbol_part_outline_in_view` takes the view's
outline state, and the Direct Selection overlay passes it.
- `hit::symbol_part_at` tests art in a layer whose Preview is off in
outline.
Consider Open Filled Paths as Closed decided whether an open path was
filled from its top fill row only. A path whose top fill is None over a
painted lower fill stayed open, and one whose only painted fill was
hidden or at 0% opacity closed. The region map, merge inputs and the
Clicking Stroke Splits the Path cut now use Appearance::has_drawn_fill,
so any shown, painted fill row above 0% opacity counts, as the canvas
paints it.
The Shape Builder's Live Paint face and edge filters had the same
top-row check; they now use has_drawn_fill and has_drawn_stroke, so a
face or edge is taken when one of its rows draws.
brush.freehand drew the plain path when `brush` named no brush in the
document or was not a string, and drew a pencil stroke for any `style`
other than "brush". It now refuses an unknown name with "no brush named
`<name>`", as brush.apply and brush.setCurrent do, a `brush` that is not
a string, and a `style` other than "pencil" or "brush". The document does
not change and no undo step is recorded. A `brush` left out or null still
draws the plain path.
The Paintbrush skips a tool brush or current brush that has been deleted
and paints with the other, or draws the plain path when neither is in the
document, so a stroke after a brush is deleted is not refused.
The canvas clips a clip group by its clipping path with the path's live
geometry effects applied, but clicks, hovers and marquees still tested
the plain clipping path. A click where a Transform effect had moved the
clip selected nothing, and a click on the clipping path's own place
selected art that was not drawn there.
- The engine registers the effect-shaped region with the doc crate
(`hit::set_clip_region`), as it does for image paint and live art. It
gives a region only when the clipping path holds a visible geometry
effect; otherwise clicks keep the plain shapes, and type keeps
counting by its frame.
- Clicks, `objects_at`, the hidden art of a selected object, the Unlock
submenu's list and marquees inside a clip group or a clipping layer
use that region. Outline view and layers with Preview off draw no
effects and keep the plain shapes; the Selection, Direct Selection
and Enclosing Lasso marquees pass the view's outline state
(`hit::marquee_in_view`). Each container around a selected object
tests its clipping path in the outline state a click has there.
- A marquee touches the clipping path itself by its own geometry, as a
click on its outline finds it, and also on the edge of the region, so
a marquee around a clipping path that an effect moved into large art
still selects it. `hit::marquee_in` keeps the plain shapes for the
Color Theme Picker, which clips by them.
- The region is kept per thread until the clipping path or the live
inputs change. A clip group's reach takes in the region's box, so
culling does not skip art the region moved past the plain clipping
path. Up to 4096 boxes are kept; when they are full, a new box
replaces only as many others as it needs room for.
Docs: docs/target-app-parity.md.
With Smart Guides on, a selection the Selection tool grabbed by one of
its anchors only landed that anchor on other anchors and centers, or
lined its bounds up. The anchor now also lands on the other objects'
paths ("path"), and where a path crosses another path or a ruler guide
("intersect"), in the order Direct Selection uses for a dragged anchor.
When the anchor lands on a path, the bounds do not also line up with
other objects, and a ruler guide nearby does not pull it off the path.
A selection grabbed anywhere else keeps lining its bounds up.
- Targets::for_move_by_anchor gathers the other art's path segments as
well, and Targets::snap_onto_path lands a point on them or on their
crossings with each other and with the ruler guides.
- MoveSnap::by_anchor uses those targets; the Selection tool picks it
when the press grabbed an anchor.
Reported by pivot-al.
Docs: docs/target-app-parity.md.
The outline a Blob Brush or Eraser drag shows was copied, flattened and
tessellated again every frame, settled parts included, so the per-frame
cost of a long stroke grew with its whole length.
- The settled outline blocks are kept as shared paths and returned as a
new Overlay::SharedPath; a block gets a new path only when it is
joined again.
- The canvas keeps the mesh each shared path was drawn with, by the
path's allocation and for the view, clip and stroke it was built for.
A frame with the same path and view draws the kept mesh; a pan, zoom
or rotation builds it once more. Lines outside the canvas get no
triangles. A frame keeps only the meshes it draws.
egui still copies each kept mesh into the frame's mesh on every repaint.
The release sends the same path.blob and path.eraseRegion command as
before. The round Eraser tip's line is unchanged.