Step 17b: bytecode-compiled text-layout, WASM library import fix
- text-layout.sx added to WASM bytecode pipeline (9K compiled) - Fix multi-list map calls (map-indexed + nth instead of map fn list1 list2) - pretext-layout-lines and pretext-position-line moved to library exports - Browser load-sxbc: handle VmSuspended for import, copy library exports to global_env after module load (define-library export fix) - compile-modules.js: text-layout in SOURCE_MAP, FILES, and entry deps - Island uses library functions (break-lines, pretext-layout-lines) instead of inlining — runs on bytecode VM when exports resolve Known issue: define-library exports don't propagate to browser global env yet. The load-sxbc import suspension handler resumes correctly but bind_import_set doesn't fire. Needs deeper investigation into how the WASM kernel's define-library registers exports vs how other libraries (adapter-html, tw) make their exports available. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
;; Pretext island — client-side text layout with live controls
|
||||
;;
|
||||
;; Uses canvas.measureText for pixel-perfect browser font measurement.
|
||||
;; All layout functions inside the island — self-contained.
|
||||
;; Calls break-lines/break-lines-greedy from lib/text-layout.sx (bytecode-compiled).
|
||||
|
||||
(defisland
|
||||
~pretext-demo/live
|
||||
@@ -16,91 +16,9 @@
|
||||
(canvas (host-call doc "createElement" "canvas"))
|
||||
(ctx (host-call canvas "getContext" "2d")))
|
||||
(let
|
||||
((measure-word (fn (word sz) (do (host-set! ctx "font" (str sz "px 'Pretext Serif', DejaVu Serif, serif")) (host-get (host-call ctx "measureText" word) "width"))))
|
||||
(sum-w
|
||||
(fn
|
||||
(widths sw from to)
|
||||
(let
|
||||
loop
|
||||
((k from) (total 0))
|
||||
(if
|
||||
(>= k to)
|
||||
(+ total (* (max 0 (- (- to from) 1)) sw))
|
||||
(loop (+ k 1) (+ total (nth widths k)))))))
|
||||
(brk-optimal
|
||||
(fn
|
||||
(widths sw mx)
|
||||
(let
|
||||
((n (len widths)))
|
||||
(if
|
||||
(<= n 0)
|
||||
(list)
|
||||
(let
|
||||
((dp (map (fn (i) (if (= i 0) (list 0 -1) (list 999999999 -1))) (range (+ n 1)))))
|
||||
(for-each
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((prev-cost (first (nth dp i))))
|
||||
(let
|
||||
try-j
|
||||
((j i))
|
||||
(when
|
||||
(< j n)
|
||||
(let
|
||||
((used (sum-w widths sw i (+ j 1))))
|
||||
(when
|
||||
(<= used (* mx 1.15))
|
||||
(let
|
||||
((slack (- mx used)))
|
||||
(let
|
||||
((bad (if (< slack 0) 100000 (let ((r (/ slack mx))) (* (* r r) (* r 1000))))))
|
||||
(let
|
||||
((cost (+ prev-cost (let ((b (+ 1 bad))) (* b b))))
|
||||
(entry (nth dp (+ j 1))))
|
||||
(when
|
||||
(< cost (first entry))
|
||||
(set!
|
||||
dp
|
||||
(map-indexed
|
||||
(fn
|
||||
(idx e)
|
||||
(if
|
||||
(= idx (+ j 1))
|
||||
(list cost i)
|
||||
e))
|
||||
dp)))
|
||||
(try-j (+ j 1)))))))))))
|
||||
(range n))
|
||||
(let
|
||||
((breaks (let trace ((pos n) (acc (list))) (let ((prev (nth (nth dp pos) 1))) (if (<= prev 0) acc (trace prev (cons prev acc)))))))
|
||||
(let
|
||||
((starts (cons 0 breaks)))
|
||||
(let
|
||||
((ends (append (rest starts) (list n))))
|
||||
(map (fn (s e) (list s e)) starts ends)))))))))
|
||||
(brk-greedy
|
||||
(fn
|
||||
(widths sw mx)
|
||||
(let
|
||||
((n (len widths)) (lines (list)) (start 0) (used 0))
|
||||
(for-each
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((w (nth widths i))
|
||||
(needed (if (= i start) w (+ used sw w))))
|
||||
(if
|
||||
(and (> needed mx) (not (= i start)))
|
||||
(do
|
||||
(set! lines (append lines (list (list start i))))
|
||||
(set! start i)
|
||||
(set! used w))
|
||||
(set! used needed))))
|
||||
(range n))
|
||||
(append lines (list (list start n)))))))
|
||||
((measure-word (fn (word sz) (do (host-set! ctx "font" (str sz "px 'Pretext Serif', DejaVu Serif, serif")) (host-get (host-call ctx "measureText" word) "width")))))
|
||||
(let
|
||||
((layout (computed (fn () (let ((sz (deref font-size)) (mw (deref max-w)) (optimal (deref use-optimal))) (let ((widths (map (fn (w) (measure-word w sz)) words)) (sw (measure-word " " sz))) (let ((ranges (if optimal (brk-optimal widths sw mw) (brk-greedy widths sw mw))) (lh (* sz 1.5))) (map (fn (line-idx) (let ((range (nth ranges line-idx)) (y (* line-idx lh))) (let ((start (first range)) (end (nth range 1))) (let ((lw (slice words start end)) (lwid (slice widths start end))) (let ((total-w (reduce + 0 lwid)) (n-gaps (max 1 (- (len lw) 1))) (is-last (= line-idx (- (len ranges) 1)))) (let ((gap (if is-last sw (/ (- mw total-w) n-gaps)))) (let pos ((i 0) (x 0) (acc (list))) (if (>= i (len lw)) {:y y :words acc} (pos (+ i 1) (+ x (nth lwid i) gap) (append acc (list {:x x :word (nth lw i)}))))))))))) (range (len ranges))))))))))
|
||||
((layout (computed (fn () (let ((sz (deref font-size)) (mw (deref max-w)) (optimal (deref use-optimal))) (let ((widths (map (fn (w) (measure-word w sz)) words)) (sw (measure-word " " sz)) (lh (* sz 1.5))) (let ((ranges (if optimal (break-lines widths sw mw) (break-lines-greedy widths sw mw)))) (pretext-layout-lines words widths ranges sw mw lh))))))))
|
||||
(div
|
||||
(~tw :tokens "space-y-4")
|
||||
(div
|
||||
|
||||
Reference in New Issue
Block a user