Commit Graph
92 Commits
Author SHA1 Message Date
bflatastic 7177f1c042 Merge main into #1021
# Conflicts:
#	ROADMAP.md
#	docs/roadmap.md
2026-10-26 10:29:24 +07:00
BFlat f93deb965b Merge pull request #661 from AganzeFelicite/fix/adobe-fonts-macos-298
M7: find fonts activated through Adobe Fonts on macOS (#298)
2026-10-26 10:23:17 +07:00
bflatastic 6c4bb00c9e Merge main into #1021
# Conflicts:
#	crates/text/src/fontdb_tests.rs
2026-10-26 10:20:43 +07:00
bflatastic 7c25399e4a Merge main into #661
# Conflicts:
#	ROADMAP.md
2026-10-26 10:03:15 +07:00
bflatastic 5cdd41a79f Merge main into #1215 2026-10-26 09:19:37 +07:00
bflatastic 7a1b9d8414 #1021: a named style's optical size follows the text size only for .sketch imports
Existing text keeps the named instance's optical size, so documents render as before; the
Sketch import stores the size as the text's opsz value instead.
2026-10-26 09:12:40 +07:00
bflatastic 07a654959a Merge main into #1021
# Conflicts:
#	docs/file-format-parity.md
2026-10-26 09:12:39 +07:00
BFlat b3f06f6eca Merge pull request #1163 from switch87/fix/linux-symbol-fallback
M9: fall back to the Noto symbol and math fonts on Linux (#1156)
2026-10-26 08:33:05 +07:00
Jindřich ŠaršonandClaude Opus 5.5 6258ad2786 M6: Sketch import: merge main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 22:23:40 +01:00
Brandon Thomas 31b857433d Merge pull request #1242 from SusieeTheLinuxUser/fix/1220-thai-backspace
Text: Backspace removes Thai and other marks one at a time (#1220)
2026-10-25 12:10:52 -04:00
Brandon Thomas 610fe374c7 Merge pull request #1218 from Salah1St/fix/justify-zwsp
M4: justified text doesn't widen U+200B
2026-10-25 12:10:47 -04:00
Jindřich ŠaršonandClaude Opus 5.5 87db9522b4 M6: Sketch import: merge main (Boards M12 and community fixes)
Conflicts resolved keeping both sides: `.sketch` stays in `is_document`
(now via `OsStr::to_str`); ROADMAP and the parity, roadmap and
file-format docs keep main's headers and rows with the `.sketch` notes
and history rows added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 19:13:03 +02:00
AganzeFelicite c743f8ec1e Merge remote-tracking branch 'upstream/main' into fix/adobe-fonts-macos-298
# Conflicts:
#	ROADMAP.md
#	crates/text/src/fontdb.rs
#	docs/roadmap.md
2026-10-24 18:20:00 +02:00
Dylan M. TaylorandClaude Sonnet 5.5 3739b2863a fix(security): cap COLR layers, PNG glyph dimensions, and layout cache capacity (#1264)
* chore: explicit test imports in engine, part 1 (Sonar S2208)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(security): cap COLR layers, PNG glyph dimensions, and layout cache capacity

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 04:41:31 -04:00
Dylan M. Taylor 0cca56984f fix(security): bound decoration steps, text-on-path elements, and rename expansions (#1257) 2026-10-24 04:39:12 -04:00
bflatastic c31f886c05 Merge main into #1215 2026-10-24 12:54:15 +07:00
Salah1StandClaude Opus 5.5 84ca850d5f M4: justified text doesn't widen U+200B
Thai, Lao, Khmer and Burmese are written without spaces between words.
Tools that know the words insert U+200B ZERO WIDTH SPACE so lines can
break between them, and line breaking already treats it as a space. But
justification counted every space-class char as a gap, so a justified
paragraph got extra room at every U+200B: visible gaps between all its
words, which is not how these scripts are justified.

Item::stretches() (a space other than U+200B) is used for the justify
gap count, the trailing width and the pen advance. Line breaking is
unchanged. Test: on a justified line of words joined by U+200B and one
real space, the extra room goes to the real space only; with no real
space the line is laid out as if left-aligned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:15:57 +07:00
SusieeTheFemboyandGPT-6 Luna 8989e7b253 Text: Backspace removes Thai and other marks one at a time (#1220)
Co-Authored-By: GPT-6 Luna <noreply@openai.com>
2026-10-24 06:27:49 +02:00
BFlat 3476f4b1e7 Merge pull request #1244 from storytold/batch/r2-1
Community batch r2-1: 63 reviewed PRs
2026-10-24 11:15:53 +07:00
bflatastic 8af2efd1b9 Batch r2-1 review: U+2007 glues beside ideographs too 2026-10-24 10:31:29 +07:00
a1a842af9a chore: resolve SonarCloud maintainability issues (#1241)
* chore: resolve SonarCloud maintainability issues

- Define SHA256_FMT constant in packaging script to remove duplicated string literal (shelldre:S1192)
- Remove redundant 'static lifetime annotations from const items (rust:S8863)
- Replace closures with method and function pointers (rust:S1612)
- Extract helper functions in synthetic document generation, bezier polyline flattening, and component restoration to reduce cognitive complexity (rust:S3776)

* fix(packaging): use verify_sha256 helper function to avoid shellcheck SC2059

* fix(engine): remove duplicate closing brace in large_document

* fix(engine): take &mut Document in restore_id_map; keep 'static on associated consts

restore_id_map allocates ids, so it needs a mutable document. Elided
lifetimes in associated consts trip elided_lifetimes_in_associated_constant,
so those annotations are restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assign positional parameters to locals in sha256 verification

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-23 23:28:13 -04:00
bflatastic 53b8b531ce Merge #1031: Treat U+2007 FIGURE SPACE as non-breaking in line breaking (@Silvertree2010) 2026-10-24 09:23:18 +07:00
Salah1StandClaude Opus 5.5 dd37c1763c M4: the Thai fallback test checks the characters it draws
Review: the test chose its Thai face, and checked each glyph's face, by
U+0E01, which the sample doesn't contain. It now asks for a face that has
every Thai character of the sample, and checks that each glyph's face has
the characters of its cluster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:36:24 +07:00
Salah1StandClaude Opus 5.5 1340e32b16 M4: Thai faces in the text fallback list
Thai typed into a layer whose font has no Thai glyphs (Inter, which new
text starts in) was drawn as missing-glyph boxes, on the desktop and on
the web, even with a Thai face embedded or installed: FALLBACK_FAMILIES
listed Latin, CJK, Hangul, Arabic and symbol families but no Thai one.

Noto Sans Thai, Noto Sans Thai UI, Leelawadee UI, Thonburi and Tahoma go
after Noto Sans Arabic; they are only consulted for characters the
layer's own font lacks. Tests: the list has a Thai face for each
platform, and with one installed or embedded every Thai cluster in a
Latin layer, marks included, is drawn from it (skips without one).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:26:37 +07:00
Gert Pellin c7d2a5f019 M9: the symbol test also looks for the Noto Sans Symbols2 spelling (#1156) 2026-10-22 21:46:12 +02:00
Gert Pellin 5a3dddc46f M9: fall back to the Noto symbol and math fonts on Linux (#1156)
Signs such as U+2316 and U+2912 are in no text face. The fallback list
had the macOS and Windows symbol fonts (Apple Symbols, Segoe UI Symbol)
but nothing a Linux install has, so they drew as empty boxes there even
with Noto Sans Symbols 2 or Noto Sans Math installed. Adds Noto Sans
Symbols, Noto Sans Symbols 2 (and the Symbols2 spelling some packages
use) and Noto Sans Math after them.
2026-10-22 21:29:58 +02:00
NetterSilverandClaude Opus 5.5 83b9f74665 Write a final Greek sigma in lower-case text layout
Found while testing crates/text/src/layout.rs:1070 (shape_segment calls TextCase::apply_after one char at a time; crates/doc/src/text.rs:124 apply_after)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 19:04:10 +02:00
NetterSilverandClaude Haiku 5.5 857762e65c Treat U+2007 FIGURE SPACE as non-breaking in line breaking
Found while testing crates/text/src/breaks.rs:42

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:36:21 +00:00
Jindřich ŠaršonandClaude Opus 5.5 7cb4168e13 M6: Sketch import: fixes from the PR review
- --no-system-fonts holds for .sketch imports too: the CLI opts the
  process out, so the import's font matching doesn't scan.
- Shared text styles get the installed family and platform tracking
  their linked layers get.
- Each text run writes its letter spacing, line height and font axes,
  neutral when it has none, instead of taking the first run's.
- The unsupported-drop hint and its catalogs list .sketch.
- A test sends damaged .sketch data through file.open and file.import.
- Stack items are matched to their source layers through a map.
- Docs: .sketch is a convert input; the Carbon kit's Sketch 47 edition
  is refused (the 68 and 83 ones open).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 09:03:17 +02:00
AganzeFelicite b13e5c4ff3 M7: doc comments on the font scan's folders and scan_dir (#298) 2026-10-22 09:00:37 +02:00
Jindřich ŠaršonandClaude Opus 5.5 f02557e8f9 M6: Sketch import: fonts by PostScript name, Sketch's natural line
The font database knows each face's PostScript name; the Sketch import
finds the installed face a file's font names (CourierNewPSMT is Courier
New Regular) and reads the family from the name only when it isn't
installed. Text without a fixed line height takes the line Sketch draws:
ascent and descent rounded to whole pixels, the line gap left out, a
fifth more for classic Mac fonts, the baseline where Sketch puts it
(measured on sketchtool renders of 80 fonts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:27:20 +02:00
Jindřich ŠaršonandClaude Opus 5.5 ad78ee94c3 M6: Sketch import: instances, artboards and Apple fonts like Sketch
Compared with Sketch's renders of a Sketch 64 file. Resized instances lay
out their layers the way Sketch does (measured: pins share the change in
proportion, a fixed size keeps its centre's share, and files before format
110 just scale); masters' backgrounds show in instances only when Sketch
includes them; swaps to a missing symbol keep the original; artboards
don't draw a style they carry. Apple's system fonts are found under the
names designs use (SF Pro, SF UI Text and Display, SF Compact), the
optical size follows the text size for named styles too, and imported
text keeps the platform's trak tracking as letter spacing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:27:20 +02:00
AganzeFelicite d68a2c54c5 Merge remote-tracking branch 'upstream/main' into fix/adobe-fonts-macos-298
# Conflicts:
#	ROADMAP.md
#	crates/text/src/fontdb.rs
#	crates/text/src/fontdb_tests.rs
#	docs/roadmap.md
2026-10-21 05:36:34 +02:00
BFlat 1abb9083c7 Merge pull request #821 from attisvalentin/fix/rescan-and-load-fonts
M4: fonts installed while the app runs: text.rescanFonts, text.loadFont, text.refit
2026-10-20 03:04:29 +07:00
bflatastic f2ede63dd9 #867: comments describe the line separator without naming another product 2026-10-20 00:00:09 +07:00
bflatastic 203ec13e03 #821: text.loadFont reads at most MAX_FONT_FILE (the font scan's 256 MiB cap) 2026-10-19 23:44:08 +07:00
AganzeFelicite 710c95e527 test(text): a selection across a line separator shows the break (#852) 2026-10-19 12:52:09 +02:00
AganzeFelicite b930ea5871 test(text): the caret's line on either side of a line separator (#852) 2026-10-19 12:13:12 +02:00
AganzeFelicite 1b66fec3ec fix(text): the caret after a line break sits on the next line
`caret` put the index right after a line break (a newline, or a line
separator) at the end of the line above, so after Enter the caret showed
on the previous line until something was typed, and Up/Down counted
lines from there. The index before the break stays at the end of its
line; the one after it is now on the next line, as after a wrap.
Selection highlights already started such lines at their own start
(#665); their comment no longer describes the old caret.
2026-10-19 12:12:54 +02:00
AganzeFelicite 9e4dcc9204 test(text): line separators in layout, lists and carets (#852) 2026-10-19 11:34:58 +02:00
AganzeFelicite 692f45123c fix(text): a line separator breaks the line inside its paragraph (#852)
Figma stores Shift+Enter as U+2028. `.fig` imports keep it, but layout
only broke lines at a newline, so imported text ran soft-broken lines
together ("Option 1SL: …"), lost the empty line of a separator followed
by a newline, and put glyph bullets on one line.

A line separator now ends its line without ending the paragraph: no
paragraph spacing and no new list marker after it, the next line keeps
the item's indent, and it draws no glyph. A trailing one leaves an empty
last line, and a line it cuts short isn't stretched when justified.
2026-10-19 11:34:47 +02:00
AganzeFelicite 855bbb328f refactor(text): Line::break_after for carets and selections
Carets, clicks and selections asked `para_end && !last_line` to mean
"the line ends with a break char". Record that on the line instead, so a
break that doesn't end the paragraph can use the same rules. No
behaviour change: today only a newline ends a line early.
2026-10-19 11:34:34 +02:00
AganzeFelicite fd02772d22 refactor(text): one helper for the chars that end a line 2026-10-19 11:34:21 +02:00
Attila Valentin NémethandClaude Opus 5.5 33c0f94cc8 M4: font review fixes: new styles of loaded families, ids checks, repeat loads
- text.rescanFonts offers a loaded family the files it hasn't read (styles
  installed since) and refits every family that gained faces; `added` still
  lists only the families that were unknown
- text.refit refuses an `ids` that isn't a list instead of refitting the
  whole document
- text.loadFont with a file already loaded returns its families without
  keeping its bytes or adding its faces again
- doc comments on the functions this change touches

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:46:20 +02:00
Attila Valentin NémethandClaude Opus 5.5 972e228f41 M4: text.rescanFonts and text.loadFont: fonts installed while the app runs
The system fonts are indexed once per process, so a font installed while
FigCraft (or `figcraft-cli mcp`) runs stayed missing until a restart.

- text.rescanFonts walks the font folders again and offers the families
  installed since (loaded families keep their faces) → {added}
- text.loadFont {path | data} adds a font file without installing it → {families}
- both clear the layout cache so text lays out again in the new face

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:13:49 +02:00
bflatastic 401af64bba Merge fix/758 into batch 16 2026-10-18 11:16:43 +07:00
bflatastic 91c80a19cc M7: find macOS's downloadable CJK system fonts (#406)
Current macOS keeps PingFang and other on-demand fonts in its asset
store, which the font scan never walked, so Chinese text showed as
boxes. The scan now also walks the com_apple_MobileAsset_Font* folders
of /System/Library/AssetsV2 (and the older /System/Library/Assets) with
the same depth, size and file checks, and Hiragino Sans GB and Heiti SC
(preinstalled) join the Chinese UI faces and the text fallbacks.
Tested with a folder laid out the same way; not run on a Mac.
2026-10-17 22:53:54 +07:00
RealtaNuaandClaude Opus 5.5 a3c5025186 M7: missing fonts window only after a file opens; wait for the font scan (#752)
From review:
- The check ran after any file.open/openRecent/import result, so a
  pasted or dropped image, reopening a file that was already open, or
  Clear recent brought the window back. It now runs only for results
  with a `summary` (a file opened, or pages imported), and never in the
  browser.
- Text > Missing fonts... before the startup scan finished listed
  installed fonts as missing. It now says it is checking the installed
  fonts and lists them once that is done
  (`figcraft_text::installed_fonts_known`, also true when system fonts
  are opted out, where checks used to wait forever).
- ROADMAP progress log and file-format-parity status line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 22:06:03 +07:00
RealtaNuaandClaude Opus 5.5 825cb1e7af M7: list the fonts a file uses that aren't installed (#752)
Text in a family that isn't installed was drawn in a fallback font
without a word. Now:

- `text.missingFonts` lists the families a document names that no
  installed or built-in font provides: text layers and their styled
  ranges, text styles, and string variables bound to a font family
  (every mode, through aliases), with the number of text layers.
- The desktop app shows a Missing fonts window after the user opens a
  file that has any: once installed fonts are indexed (before that every
  one of them would count as missing) and after any import report is
  closed. Files named on the command line count. Programmatic opens and
  the browser build never open it by themselves. Text > Missing fonts...
  shows it for the file in front; Escape closes it.
- `figcraft-cli info` prints `missing font` lines (`missingFonts` with
  --json).
- file-format-parity: the row claimed REST import warnings that no code
  produced.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 21:49:32 +07:00
bflatastic feeb9f71db Merge fix/671 into batch 13 2026-10-17 17:19:52 +07:00