158 lines
7.0 KiB
EmacsLisp
158 lines
7.0 KiB
EmacsLisp
;;; ebox-render-context.el --- Shared render context binding -*- lexical-binding: t; -*-
|
|
|
|
;;; Commentary:
|
|
;; Owns the compile-safe render-context binding shared by the incremental
|
|
;; planner and the buffer backend. Keeping this macro below both modules avoids
|
|
;; their runtime dependency cycle becoming an invalid byte-compiled function.
|
|
|
|
;;; Code:
|
|
|
|
(defvar ebox-viewport-width nil)
|
|
(defvar ebox-viewport-height nil)
|
|
(defvar ebox--render-runtime-revision nil)
|
|
(defvar ebox--surface-materialization-active nil)
|
|
(defvar ebox--render-cache-table nil)
|
|
(defvar ebox--render-cache-signature-cache nil)
|
|
(defvar ebox--viewport-dependent-node-ids-cache nil)
|
|
(defvar ebox--viewport-dependent-subtree-cache nil)
|
|
(defvar ebox--viewport-height-dependent-subtree-cache nil)
|
|
(defvar ebox--flex-content-min-width-table nil
|
|
"Render-owned box measurements reusable by native scene compilation.")
|
|
|
|
(defvar ebox--render-owned-text-values nil
|
|
"Candidate-local text-property values explicitly created by Ebox.")
|
|
|
|
(defvar ebox--render-output-provenance-table
|
|
(make-hash-table :test #'eq :weakness 'key)
|
|
"Weak map from rendered strings to Ebox-owned property values.")
|
|
|
|
(defun ebox--render-owned-text-values-for (property &optional create)
|
|
"Return the active candidate registry for PROPERTY when CREATE is non-nil."
|
|
(when (hash-table-p ebox--render-owned-text-values)
|
|
(or (gethash property ebox--render-owned-text-values)
|
|
(when create
|
|
(let ((values (make-hash-table :test #'eq :weakness 'key)))
|
|
(puthash property values ebox--render-owned-text-values)
|
|
values)))))
|
|
|
|
(defun ebox--register-render-owned-text-value (property value)
|
|
"Register Ebox-created VALUE for PROPERTY in the active render candidate."
|
|
(when value
|
|
(when-let ((values (ebox--render-owned-text-values-for property t)))
|
|
(puthash value t values)))
|
|
value)
|
|
|
|
(defun ebox--render-owned-text-value-p (property value &optional registry)
|
|
"Return non-nil when VALUE is Ebox-owned for PROPERTY.
|
|
REGISTRY defaults to the active render candidate."
|
|
(let ((ebox--render-owned-text-values
|
|
(or registry ebox--render-owned-text-values)))
|
|
(when-let ((values (ebox--render-owned-text-values-for property)))
|
|
(gethash value values))))
|
|
|
|
(defun ebox--register-render-owned-face-values (source rendered)
|
|
"Register Ebox-generated face identities added to RENDERED from SOURCE."
|
|
(when (and (stringp source)
|
|
(stringp rendered)
|
|
(= (length source) (length rendered))
|
|
(hash-table-p ebox--render-owned-text-values))
|
|
(let ((position 0)
|
|
(length (length rendered)))
|
|
(while (< position length)
|
|
(let ((next
|
|
(min (or (next-property-change position source) length)
|
|
(or (next-property-change position rendered) length)))
|
|
(source-face (get-text-property position 'face source))
|
|
(rendered-face (get-text-property position 'face rendered)))
|
|
(when (and rendered-face (null source-face))
|
|
(ebox--register-render-owned-text-value 'face rendered-face))
|
|
(setq position next)))))
|
|
rendered)
|
|
|
|
(defun ebox--record-render-output-provenance (rendered)
|
|
"Record owned property identities actually present in RENDERED."
|
|
(when (and (stringp rendered)
|
|
(hash-table-p ebox--render-owned-text-values))
|
|
(let ((provenance (make-hash-table :test #'eq))
|
|
(position 0)
|
|
(length (length rendered)))
|
|
(remhash rendered ebox--render-output-provenance-table)
|
|
(while (< position length)
|
|
(let ((next (or (next-property-change position rendered) length))
|
|
(properties (text-properties-at position rendered)))
|
|
(while properties
|
|
(let* ((property (pop properties))
|
|
(value (pop properties))
|
|
(owned (ebox--render-owned-text-value-p property value)))
|
|
(when owned
|
|
(let ((values (or (gethash property provenance)
|
|
(let ((new (make-hash-table
|
|
:test #'eq :weakness 'key)))
|
|
(puthash property new provenance)
|
|
new))))
|
|
(puthash value t values)))))
|
|
(setq position next)))
|
|
(when (> (hash-table-count provenance) 0)
|
|
(puthash rendered provenance ebox--render-output-provenance-table))))
|
|
rendered)
|
|
|
|
(defun ebox--replay-render-output-provenance (rendered)
|
|
"Replay owned property identities recorded for RENDERED into this candidate."
|
|
(when (and (stringp rendered)
|
|
(hash-table-p ebox--render-owned-text-values))
|
|
(when-let ((provenance
|
|
(gethash rendered ebox--render-output-provenance-table)))
|
|
(maphash
|
|
(lambda (property values)
|
|
(let ((owned (ebox--render-owned-text-values-for property t)))
|
|
(maphash (lambda (value _marker)
|
|
(puthash value t owned))
|
|
values)))
|
|
provenance)))
|
|
rendered)
|
|
|
|
(declare-function ebox--buffer-render-state
|
|
"ebox-incremental" (buffer))
|
|
|
|
(defmacro ebox--with-buffer-render-context (buffer &rest body)
|
|
"Evaluate BODY using BUFFER's stored render context."
|
|
(declare (indent 1) (debug t))
|
|
(let ((target-buffer (make-symbol "target-buffer"))
|
|
(render-state (make-symbol "render-state")))
|
|
`(let* ((,target-buffer ,buffer)
|
|
(,render-state
|
|
(ebox--buffer-render-state ,target-buffer)))
|
|
(with-current-buffer ,target-buffer
|
|
(let* ((ebox-viewport-width
|
|
(plist-get ,render-state :viewport-width))
|
|
(ebox-viewport-height
|
|
(plist-get ,render-state :viewport-height))
|
|
(ebox--render-runtime-revision
|
|
(plist-get ,render-state :runtime-revision))
|
|
(ebox--surface-materialization-active t)
|
|
(ebox--render-cache-table
|
|
(plist-get ,render-state :render-cache))
|
|
(ebox--render-cache-signature-cache
|
|
(or ebox--render-cache-signature-cache
|
|
(plist-get ,render-state :render-signature-cache)
|
|
(make-hash-table :test 'eq)))
|
|
(ebox--viewport-dependent-node-ids-cache
|
|
(or ebox--viewport-dependent-node-ids-cache
|
|
(make-hash-table :test 'eq)))
|
|
(ebox--viewport-dependent-subtree-cache
|
|
(or ebox--viewport-dependent-subtree-cache
|
|
(make-hash-table :test 'eq)))
|
|
(ebox--viewport-height-dependent-subtree-cache
|
|
(or ebox--viewport-height-dependent-subtree-cache
|
|
(plist-get
|
|
,render-state
|
|
:viewport-height-dependent-subtree-cache)
|
|
(make-hash-table :test 'eq)))
|
|
(ebox--flex-content-min-width-table
|
|
(or ebox--flex-content-min-width-table
|
|
(plist-get ,render-state :flex-content-min-widths))))
|
|
,@body)))))
|
|
|
|
(provide 'ebox-render-context)
|
|
;;; ebox-render-context.el ends here
|