Step 17b: Pretext — DOM-free text layout with otfm font measurement
Pure SX text layout library with one IO boundary (text-measure perform). Knuth-Plass optimal line breaking, Liang's hyphenation, position calculation. Library (lib/text-layout.sx): - break-lines: Knuth-Plass DP over word widths - break-lines-greedy: simple word-wrap for comparison - hyphenate-word: Liang's trie algorithm - position-line/position-lines: running x/y sums - measure-text: single perform (text-measure IO) Server font measurement (otfm): - Reads OpenType cmap + hmtx tables from .ttf files - DejaVu Serif/Sans bundled in shared/static/fonts/ - _cek_io_resolver hook: perform works inside aser/eval_expr - JIT VM suspension inline resolution for IO in compiled code ~font component (shared/sx/templates/font.sx): - Works like ~tw: emits @font-face CSS via cssx scope - Sets font-family on parent via spread - Deduplicates font declarations Infrastructure fixes: - stdin load command: per-expression error handling (was aborting on first error) - cek_run IO hook: _cek_io_resolver in sx_types.ml - JIT VmSuspended: inline IO resolution when resolver installed - ListRef handling in IO resolver (perform creates ListRef, not List) Demo page at /sx/(applications.(pretext)): - Hero: justified paragraph with otfm-measured proportional widths - Greedy vs Knuth-Plass side-by-side comparison - Badness scoring visualization - Hyphenation syllable decomposition 25 new tests (spec/tests/test-text-layout.sx), 3201/3201 passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
;; Pretext demo — DOM-free text layout
|
||||
;;
|
||||
;; Visual-first: shows typeset text, then explains how.
|
||||
;; Uses measure-text (perform) for real glyph measurement.
|
||||
;; Uses measure-text (perform) for glyph measurement.
|
||||
|
||||
;; Compute positioned word data for one line.
|
||||
(define
|
||||
@@ -45,15 +45,6 @@
|
||||
{:y y :words (pretext-position-line lw lwid gap)}))))))
|
||||
(range n-lines)))))
|
||||
|
||||
;; Measure all words and return widths list
|
||||
(define
|
||||
pretext-measure-words
|
||||
(fn
|
||||
(words font size)
|
||||
(map
|
||||
(fn (w) (let ((m (measure-text font size w))) (get m :width)))
|
||||
words)))
|
||||
|
||||
;; Render pre-computed positioned lines
|
||||
(defcomp
|
||||
~pretext-demo/render-paragraph
|
||||
@@ -109,13 +100,23 @@
|
||||
(font "serif")
|
||||
(size 15))
|
||||
(let
|
||||
((sw (pretext-measure-words sample-words font size))
|
||||
(space-m (measure-text font size " "))
|
||||
(n-words (len sample-words)))
|
||||
((sw (list)) (n-words (len sample-words)))
|
||||
(for-each
|
||||
(fn
|
||||
(w)
|
||||
(let
|
||||
((m (measure-text font size w)))
|
||||
(append! sw (get m :width))))
|
||||
sample-words)
|
||||
(let
|
||||
((space-w (get space-m :width)))
|
||||
((space-m (measure-text font size " "))
|
||||
(space-w (get (measure-text font size " ") :width)))
|
||||
(div
|
||||
(~tw :tokens "space-y-10")
|
||||
(begin
|
||||
(~tw :tokens "space-y-10")
|
||||
(~font
|
||||
:family "Pretext Serif"
|
||||
:src "/static/fonts/DejaVuSerif.ttf"))
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
@@ -166,11 +167,6 @@
|
||||
(div
|
||||
(~tw :tokens "grid grid-cols-1 md:grid-cols-2 gap-4")
|
||||
(~pretext-demo/render-paragraph
|
||||
:words sample-words
|
||||
:widths sw
|
||||
:space-width space-w
|
||||
:max-width nm
|
||||
:line-height 22
|
||||
:lines (pretext-layout-lines
|
||||
sample-words
|
||||
sw
|
||||
@@ -178,14 +174,11 @@
|
||||
space-w
|
||||
nm
|
||||
22)
|
||||
:max-width nm
|
||||
:line-height 22
|
||||
:n-words n-words
|
||||
:label "Greedy (browser default)")
|
||||
(~pretext-demo/render-paragraph
|
||||
:words sample-words
|
||||
:widths sw
|
||||
:space-width space-w
|
||||
:max-width nm
|
||||
:line-height 22
|
||||
:lines (pretext-layout-lines
|
||||
sample-words
|
||||
sw
|
||||
@@ -193,6 +186,8 @@
|
||||
space-w
|
||||
nm
|
||||
22)
|
||||
:max-width nm
|
||||
:line-height 22
|
||||
:n-words n-words
|
||||
:label "Knuth-Plass optimal"))))
|
||||
(div
|
||||
|
||||
Reference in New Issue
Block a user