Commit Graph
34 Commits
Author SHA1 Message Date
BFlat 7dd71a6972 Merge pull request #6708 from dotCooCoo/feat/mojikumi-line-end-fit
Type: Mojikumi spacing at line ends counts when lines break
2026-11-12 09:32:21 +07:00
BFlat 7739fdbe50 Merge pull request #6677 from storytold/fix/sec-text-fallback-scans
Text: bounded font fallback file searches, COLR layer outlines, frame baseline search and glyph outline size
2026-11-12 09:23:32 +07:00
dotCooCoo b89a6e8ba1 Type: Block's word gap leaves the paragraphs' word spacing as set
The word gap is now the Desired word spacing the layout uses for area type
with Block on (TextObject::layout_justification), with Minimum and Maximum
moved out to it when it lies outside them. The paragraphs keep their own
Justification values, so a wide gap no longer leaves a 1,000 % Maximum
behind, and turning Block off brings back the paragraph's own Desired
value. The SVG writer reads the same values.

- The Contextual Task Bar offers Dynamic Text for area type outside a
  thread, beside Convert To Point Type.
- type.dynamicText with wordGap or lineGap and no area type in the
  selection is an error instead of being ignored.
- Docs: docs/mcp.md, params text, docs/target-app-parity.md.
2026-11-11 15:49:16 -08:00
dotCooCoo 253c60a23e Type: a line's first word is measured as set when looking for room
In a frame that is not a rectangle, or with text wrap, layout moves a
line down to the first span wide enough for its first word. The word
was measured at full width before Mojikumi set an opening bracket at
the line's start flush, and with its last character at full width, so
a word that fit as set moved down to a wider line. It also ended at any
break opportunity, so an opening bracket counted without the character
kinsoku keeps with it and could be placed alone on a line too narrow
for that character.

- word_width ends the word only where break_line may end a line: at a
  cluster end that kinsoku allows, not inside a No Break run, whose
  spaces count. It leaves out the spaces at the word's end and narrows
  its last glyph by the Mojikumi line-end credit.
- place_flow_line measures the word after the opening-bracket trim, and
  the Every-line Composer's first-line placement takes off the same
  start credit, so the composed widths match the placed lines.
2026-11-11 15:20:50 -08:00
dotCooCoo a5bfa524dc Type: Mojikumi spacing at line ends counts when lines break
With Line-end Punctuation Half Width, a closing bracket, comma or full
stop ending a line is set half width, but both composers measured it at
full width. A closing bracket that fit only at half width went to the
next line with the character before it, and so did a comma or full stop
with Burasagari None.

The single-line and every-line composers now measure each candidate
line with its last character set as narrow as Mojikumi sets it, using
the same rule the line is drawn with. A mark that already lost its half
to the punctuation after it and a line ending in a hyphen take nothing
more off, and the quarter em between Japanese and Latin text counts only
where the line ends. Kinsoku Shori Type measures the pushed-in and
pushed-out lines the same way. Right-to-left lines and Mojikumi None
break as before.

A test font sets ideographs and Japanese punctuation one em wide, so
the layout tests run without system fonts.
2026-11-11 15:20:34 -08:00
Dylan M. Taylor 21e6524f06 Text: colour layers stop drawing outlines once over budget, one frame's baseline search has a total step budget, a glyph outline keeps at most a million elements 2026-11-11 20:24:43 +00:00
jmvergesandClaude Opus 5.5 9f80b4daae Type: aligned lines leave the tracking after their last character out (#6610)
A centred or right-aligned line of tracked type was measured with the
tracking after its last character, so it sat half that tracking
(centred) or the whole tracking (right-aligned) left of where the page
of users' .ai files draws it. That page aligns a line as wide as its
characters without that tracking.

Shaping now records the tracking each glyph's advance holds
(SGlyph::tracking), and a line that isn't justified leaves its last
character's out of the width it is aligned by. The last character is
the last one the line draws before a paragraph's end, a forced line
break or the spaces a wrap leaves; spaces or a tab typed before a
paragraph's end or a forced line break keep the letter's tracking, as
the page does. Forced line breaks and wraps aren't in the files: they
follow the rule so that turning a wrap into a paragraph or a forced line
break keeps the line in place. Hyphenated lines, lines whose last
character hangs, vertical and right-to-left lines and type on a path
keep it. The tracking stays in the glyph's advance, so the caret,
selections, line breaking and Fit Headline are unchanged.
LineInfo::trailing gives the amount. Right-aligned area type sets the
text after its last tab the same way.

What aligns by line widths follows. Convert To Area Type makes its
frame end where the lines are aligned, with room for the tracking, so
tracked type converted either way stays in place. Affinity import lines
up differently aligned paragraphs of artistic text by the aligned
widths. SVG import moves a centred or right-aligned letter-spaced line
back by its share of the last letter spacing, so it stays where a reader
draws it and SVG export, which anchors lines at the end of their
advances, reads back unchanged.

Centred and right-aligned tracked type lays out differently than before
in every document.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:07:40 +00:00
M Balazs PC b64cfed610 Merge remote-tracking branch 'origin/main' into fix/ai-right-aligned-tabs
# Conflicts:
#	crates/text/src/layout/flow.rs
#	docs/file-format-parity.md
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-09 04:48:48 +01:00
dotCooCoo 6e8e1e213e Type: a pushed-in line leaves the gap after inline art open
Kinsoku push-in room does not count a gap after inline art or inside a list marker, but the squeeze also closed those gaps. The squeeze now applies only to the gaps the room counts.
2026-11-08 18:47:54 -08:00
dotCooCoo 0ce616da4b Merge main into feat/kinsoku-shori-type
# Conflicts:
#	crates/engine/src/cmd/panelcmds.rs
#	crates/text/src/layout/breaking.rs
#	crates/ui-egui/src/panels/paragraph.rs
#	docs/target-app-parity.md
2026-11-08 16:13:35 -08:00
M Balazs PC b3fb745575 Merge remote-tracking branch 'origin/main' into fix/ai-right-aligned-tabs
# Conflicts:
#	crates/text/src/layout/flow.rs
2026-11-08 22:25:23 +01:00
dotCooCoo 7b8d5ba8f5 Type: Tab and Shift+Tab move a list item down and up a level
Squashed from #5037 onto main.
2026-11-09 03:39:05 +07:00
M Balazs PC a24ab06c6d Merge branch 'fix/ai-type-leading-forced-breaks' into fix/ai-right-aligned-tabs
# Conflicts:
#	crates/engine/tests/import_fuzz.rs
#	crates/eps/src/import/ate.rs
2026-11-08 14:58:13 +01:00
M Balazs PC f5c3f47612 Merge remote-tracking branch 'origin/main' into fix/ai-type-leading-forced-breaks
# Conflicts:
#	crates/eps/src/import/ate.rs
#	crates/text/src/layout.rs
2026-11-08 14:57:14 +01:00
dotCooCoo f42fdf900f Type: layout looks up each style run's face once
Layout kept no record of a run's face, so each paragraph looked up the face
of its first character three times for its line metrics and once more to
shape it. The layout now keeps each run's face the first time it is looked
up and uses it for shaping, for paragraph metrics, for on-path type's empty
line and for the column offset of vertical point type. Glyphs, positions,
bounds and baselines do not change.

A test-only helper lays text out looking every face up at each use, and a
new test requires point, vertical point, area and path type laid out both
ways to match exactly.

The layouts of 5,000 short point type objects take a median of 215 million
CPU cycles of the laying-out thread instead of 236 million in a release
build (11 alternating runs of each build on Windows 11, measured while
other builds were running).
2026-11-08 12:21:32 +07:00
M Balazs PC 8561ef351c Docs: the line layout functions the tab fix touches say what they do 2026-11-07 19:34:47 +01:00
M Balazs PC 0234de1302 Merge branch 'fix/ai-type-leading-forced-breaks' into fix/ai-right-aligned-tabs
# Conflicts:
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-07 19:31:52 +01:00
M Balazs PC 4bfd7a207d Docs: the functions the line layout fixes touch say what they do 2026-11-07 19:30:49 +01:00
M Balazs PC d9fdd7a072 Type: the last tab of right-aligned area type leaves room for the hyphen a hyphenated line ends with 2026-11-07 19:25:01 +01:00
M Balazs PC 36511e1bbd Merge branch 'fix/ai-type-leading-forced-breaks' into fix/ai-right-aligned-tabs 2026-11-07 19:10:42 +01:00
M Balazs PC c0341c3fff Type: a paragraph ending in a soft return justifies the line the soft return ends
A paragraph that ends in a soft return ends with the empty line after it,
so the line the soft return ends is justified like any other; it was taken
for the paragraph's last line and left aligned.
2026-11-07 19:10:21 +01:00
M Balazs PC a4e315796b Type: right-aligned area type sets the text after a line's last tab against the edge
In right-aligned area type, the text before a line's last tab sits at its
stops, measured from the left edge, and the text after it (none when the
tab ends the line) against the right edge. The line was laid out from the
left and aligned as a whole, which moved its start off the left edge and
its tabs' text off their stops. Illustrator's own layout in a user's .ai
sets its price lists so. Centred and justified lines are aligned as a
whole as before.
2026-11-07 18:49:19 +01:00
M Balazs PC 0f0e707e60 Type: a line a soft return ends is justified as a wrapped line is
In Justify Left, Center or Right, only the paragraph's last line keeps its
alignment; a line that a soft return (U+2028) ends is spread to the frame's
edges like any wrapped line. Illustrator's own layout in a user's .ai sets
such lines justified, and VectorCraft left them ragged.
2026-11-07 16:57:21 +01:00
dotCooCoo 6d38e94f19 Merge current main into Kinsoku Shori Type 2026-11-03 12:25:55 -08:00
dotCooCoo 63ac1395fd Type: control Kashidas for selected characters 2026-11-03 23:29:52 +07:00
dotCooCoo 0465fb8336 Type: push-in closes no gap inside a cluster and measures along the line
A push-in no longer counts or closes the gap between two glyphs of one
shaped character, and CJK justification adds no space there either.
The share of an em each gap closes by is measured along the line: at
the character's Horizontal Scale, or at its Vertical Scale for an
upright character in vertical type whose font's vertical metrics set
its length down the column. Before, horizontal text at 200% Vertical
Scale closed its gaps by twice as much.
2026-11-01 08:36:32 -08:00
dotCooCoo e1440a3a90 Paragraph: Kinsoku Shori Type chooses Push In First, Push Out First or Push Out Only
The Paragraph panel menu (with the East Asian options) gains Kinsoku Shori
Type, and text.setFormat takes kinsokuType. Where the Kinsoku Set keeps a
character off the start of the next line or the end of this one, Push In
First sets it on the line and closes the line's gaps next to CJK
characters to fit, each by at most a tenth of an em of the character
before it; a line that cannot close up that much, or that holds a tab,
pushes out. With Optical Margin Alignment or Roman Hanging Punctuation
on, the gaps that hanging punctuation keeps open are not counted. Push
Out First pushes in only when pushing out would leave the line more than
an em short. Push Out Only, the default, is the line breaking area type
had before, so existing documents lay out unchanged. The setting does
nothing with Kinsoku Set None, is saved only when it is not Push Out
Only, and paragraph styles carry it. Reset Panel sets it back to Push
Out Only.

Docs: docs/mcp.md, docs/type-parity.md, docs/target-app-parity.md.
2026-10-31 21:14:57 -07:00
bflatastic 084f4f3240 Text: a line ending at the paragraph's start can't underflow 2026-10-29 20:36:07 +07:00
Taha-Mahmoodi 7511f84d5d Layout: end manual tate-chu-yoko at soft return, and use separator metrics for empty continuation line 2026-10-29 20:36:05 +07:00
Taha-Mahmoodi b6df1ef0b1 Type: handle soft return in no-break runs, event modifiers, trailing breaks, and tabs 2026-10-29 20:36:05 +07:00
Taha-Mahmoodi d89031848c Fix #2754: Shift+Enter inserts a soft return (forced line break)
In typography and Illustrator, Shift+Enter inserts a soft return (forced
line break) rather than ending the paragraph. Text wraps to the next line
without applying paragraph-level spacing (space before/after, first-line
indents), list continuation lines keep their parent item without repeating
markers, and justified text does not stretch lines ending with a soft return.

- Forward active modifier keys for Enter in ui-egui shortcuts so the tool
  detects Shift+Enter.
- Type tool inserts U+2028 (LINE SEPARATOR) on Shift+Enter.
- Text shaping and layout treat U+2028 as an invisible zero-advance control
  character, breaking the line in point and area type.
- Paragraph spacing and list markers apply once per paragraph as intended.
2026-10-29 20:36:05 +07:00
Dylan M. Taylor 86c81f21d2 Restore RTL Mojikumi condition, dropped layout comments and xtask root
- flow.rs: an opening bracket starting a wrapped line is set flush unless the paragraph is
  right to left, as before the split (it had become !vertical, so vertical text with
  LineEndHalf lost the flush and RTL paragraphs gained it). PlacementContext carries rtl.
- flow.rs, ruby.rs: put back the comments the split dropped (JLREQ, burasagari, Optical
  Margin Alignment, kashidas, ruby phases).
- xtask root(): the parent directory, not .../xtask/..
2026-10-28 17:20:12 -04:00
Dylan M. Taylor 0e2815629f refactor(text): split flow and ruby layout phases 2026-10-27 17:47:12 +00:00
aiongg a8935c0ada refactor(text): move layout.rs items to layout/{bidi,breaking,driver,flow,on_path,region,ruby,vertical}.rs 2026-10-26 22:01:25 +00:00