ebox/tests/ebox-font-tests.el
Kinneyzhang 79f5bc23d1 feat: add CSS sizing and native text interaction capabilities
Normalize size units and intrinsic sizing across Elisp and native layout. Add help, pointer, hover-style and keymap support with reusable interaction adapters.

Keep content updates local, preserve scroll caches and hover borders, and avoid rebuilding retained plans and ownership metadata for stable geometry.

Validation: make check and native-rust-tests passed; targeted native interaction and scroll publication regressions passed.
2026-09-09 22:25:18 +08:00

153 lines
7.0 KiB
EmacsLisp

;;; ebox-font-tests.el --- Font projection contracts -*- lexical-binding: t; -*-
;;; Code:
(require 'ert)
(require 'ebox)
(ert-deftest ebox-canonical-property-cutover-shares-one-resolved-font-fact ()
"Real Surface measurement and paint share one capability-resolved fact."
(let* ((ebox-font--cache (make-hash-table :test #'equal))
(resolver-calls 0)
(ebox-font--resolver
(lambda (face _window)
(cl-incf resolver-calls)
(list :identity (list 'resolved-font (copy-tree face))
:metrics (vector 'metrics (copy-tree face))))))
(let* ((below
(ebox-font--project
:size 1.39 :weight 'normal :style 'normal
:capability-signature 'display-a))
(above
(ebox-font--project
:size 1.4 :weight 'normal :style 'normal
:capability-signature 'display-a))
(same
(ebox-font--project
:size 1.4 :weight 'normal :style 'normal
:capability-signature 'display-a))
(changed-capability
(ebox-font--project
:size 1.4 :weight 'normal :style 'normal
:capability-signature 'display-b)))
(should (= (ebox-font-fact-requested-decipoints below) 10))
(should (= (ebox-font-fact-requested-decipoints above) 11))
(should (eq above same))
(should-not (eq above changed-capability))
(let ((identity (ebox-font-fact-resolved-font-identity above))
(metrics (ebox-font-fact-measurement-metrics above)))
(setf (plist-get identity :css-weight) 900)
(aset metrics 0 'damaged)
(should (= (plist-get
(ebox-font-fact-resolved-font-identity above)
:css-weight)
400))
(should (eq (aref (ebox-font-fact-measurement-metrics above) 0)
'metrics)))
(should (= resolver-calls 3)))
(setq resolver-calls 0
ebox-font--cache (make-hash-table :test #'equal))
(let ((capability 'display-a)
(buffer (generate-new-buffer " *ebox-font-contract*")))
(unwind-protect
(cl-letf (((symbol-function 'ebox--display-signature-for-window)
(lambda (_window) capability)))
(ebox-render-to-buffer
buffer
(ebox-build
'(box :width (vw 100)
(text :font-size 16 :font-style italic "A"))))
(let* ((state-a (ebox--buffer-render-state buffer))
(node-a
(car (ebox-tree-node-children
(plist-get state-a :root-node))))
(fact-a (plist-get node-a :ebox-font-fact))
(measurement-fact nil)
(paint-fact nil)
(measurement-function
(symbol-function 'ebox-font-measurement-face))
(paint-function (symbol-function 'ebox-font-paint-face))
measured face)
(cl-letf (((symbol-function 'ebox-font-measurement-face)
(lambda (projection)
(setq measurement-fact projection)
(funcall measurement-function projection)))
((symbol-function 'ebox-font-paint-face)
(lambda (projection)
(setq paint-fact projection)
(funcall paint-function projection))))
(setq measured (ebox--propertize-typography "A" node-a)
face (ebox-buffer--font-face node-a)))
(should (ebox-font-fact-p fact-a))
(should (= resolver-calls 1))
(should (= (hash-table-count ebox-font--cache) 1))
(should (= (ebox-font-fact-requested-decipoints fact-a) 120))
(should (eq fact-a measurement-fact))
(should (eq fact-a paint-fact))
(should (integerp (plist-get face :height)))
(should (= (plist-get face :height) 120))
(should (eq (plist-get face :slant) 'italic))
(should (numberp (ebox-string-pixel-width measured)))
(setq capability 'display-b)
(let ((tp--surface-publication-step-function
(lambda (step _surface)
(when (eq step 'client-state)
(error "Reject font capability publication")))))
(should-error
(ebox-surface-update-buffer-viewport
buffer (plist-get state-a :viewport-width)
(plist-get state-a :viewport-height))))
(let* ((rolled-back (ebox--buffer-render-state buffer))
(rolled-back-node
(car (ebox-tree-node-children
(plist-get rolled-back :root-node)))))
(should (eq rolled-back state-a))
(should (eq (plist-get rolled-back-node :ebox-font-fact)
fact-a)))
(ebox-surface-update-buffer-viewport
buffer (plist-get state-a :viewport-width)
(plist-get state-a :viewport-height))
(let* ((state-b (ebox--buffer-render-state buffer))
(node-b
(car (ebox-tree-node-children
(plist-get state-b :root-node))))
(fact-b (plist-get node-b :ebox-font-fact)))
(should-not (eq fact-a fact-b))
(should (eq (ebox-font-fact-capability-signature fact-b)
'display-b))
(should (= resolver-calls 2))
(should (= (hash-table-count ebox-font--cache) 2)))))
(when (buffer-live-p buffer)
(kill-buffer buffer))))))
(ert-deftest ebox-relative-font-weight-resolves-before-emacs-paint ()
"CSS relative weight should not leak into an Emacs face attribute."
(let ((ebox-font--cache (make-hash-table :test #'equal))
(ebox-font--resolver
(lambda (face _window)
(list :identity (list :face face) :metrics nil)))
(buffer (generate-new-buffer " *ebox-font-relative*")))
(unwind-protect
(cl-letf (((symbol-function 'ebox--display-signature-for-window)
(lambda (_window) 'display-a)))
(ebox-render-to-buffer
buffer
(ebox-build
'(box :font-weight 400
(text :font-weight bolder "Bold"))))
(let* ((root (plist-get (ebox--buffer-render-state buffer)
:root-node))
(child (car (ebox-tree-node-children root)))
(fact (plist-get child :ebox-font-fact)))
(should (= (plist-get
(ebox-font-fact-resolved-font-identity fact)
:css-weight)
700))
(should (eq (plist-get (ebox-font-paint-face fact) :weight)
'bold))))
(when (buffer-live-p buffer)
(kill-buffer buffer)))))
(provide 'ebox-font-tests)
;;; ebox-font-tests.el ends here