org-latex-preview: Fix process filter timing errs

* lisp/org-latex-preview.el (org-latex-preview--create-image-async,
org-latex-preview--latex-preview-filter,
org-latex-preview--dvipng-filter, org-latex-preview--dvisvgm-filter,
org-latex-preview--place-images): The dvipng and latex-preview filters
run concurrently (interleaved), and both contribute image metadata.
So caching/placing images cannot be associated with the dvipng filter,
this leads to non-deterministic errors where preview images can have
incomplete metadata.  To fix this, check if we are using dvipng when
running the LaTeX filter, and place images from whichever of the two
filters processes each fragment second.

Refactor: Move the image placement/caching logic fully to
`org-latex-preview--place-images' instead of duplicating code in all
three (latex-filter, dvipng and dvisvgm) previews.
This commit is contained in:
Karthik Chikmagalur 2023-10-21 15:38:41 -07:00 committed by TEC
parent 5210d52d20
commit 2ff67428fa
Signed by: tec
SSH Key Fingerprint: SHA256:eobz41Mnm0/iYWBvWThftS0ElEs1ftBr6jamutnXc/A
1 changed files with 53 additions and 45 deletions

View File

@ -1332,7 +1332,8 @@ Returns a list of async tasks started."
;; ;;
;; ⟶ stdout to `org-latex-preview--latex-preview-filter' ;; ⟶ stdout to `org-latex-preview--latex-preview-filter'
;; ├─ read preview fontsize ;; ├─ read preview fontsize
;; └─ capture compilation errors ;; ├─ capture compilation errors
;; └─ (conditionally) update overlays in buffer with png images and metadata
;; ;;
;; ⟶ stdout to `org-latex-preview--dvisvgm-filter' ;; ⟶ stdout to `org-latex-preview--dvisvgm-filter'
;; ├─ read preview image metadata ;; ├─ read preview image metadata
@ -1817,7 +1818,8 @@ fragments in EXTENDED-INFO."
"\\(?:^Preview: Tightpage.*$\\)?\n! Preview: Snippet [0-9]+ ended.(\\([0-9]+\\)\\+\\([0-9]+\\)x\\([0-9]+\\))") "\\(?:^Preview: Tightpage.*$\\)?\n! Preview: Snippet [0-9]+ ended.(\\([0-9]+\\)\\+\\([0-9]+\\)x\\([0-9]+\\))")
(fragments (plist-get extended-info :fragments)) (fragments (plist-get extended-info :fragments))
(tightpage-info (plist-get extended-info :tightpage)) (tightpage-info (plist-get extended-info :tightpage))
preview-marks) (concurrentp (eq (plist-get extended-info :processor) 'dvipng))
preview-marks fragments-to-show)
(beginning-of-line) (beginning-of-line)
(save-excursion (save-excursion
(while (re-search-forward preview-start-re nil t) (while (re-search-forward preview-start-re nil t)
@ -1893,9 +1895,15 @@ fragments in EXTENDED-INFO."
(format "l.%d" (format "l.%d"
(- (string-to-number (substring linum 2)) (- (string-to-number (substring linum 2))
(nth 3 (car preview-marks))))) (nth 3 (car preview-marks)))))
errors-substring)))) errors-substring)))
(when (and concurrentp (plist-get fragment-info :path))
;; path has been recorded by dvipng filter, can display image
(push fragment-info fragments-to-show)))
(goto-char (caar preview-marks))) (goto-char (caar preview-marks)))
(setq preview-marks (cdr preview-marks))))) (setq preview-marks (cdr preview-marks)))
(when fragments-to-show
(org-latex-preview--place-images
extended-info (nreverse fragments-to-show)))))
(defun org-latex-preview--dvisvgm-filter (_proc _string extended-info) (defun org-latex-preview--dvisvgm-filter (_proc _string extended-info)
"Look for newly created images in the dvisvgm stdout buffer. "Look for newly created images in the dvisvgm stdout buffer.
@ -1932,14 +1940,7 @@ EXTENDED-INFO, and displayed in the buffer."
(when fragments-to-show (when fragments-to-show
(setq fragments-to-show (nreverse fragments-to-show)) (setq fragments-to-show (nreverse fragments-to-show))
(mapc #'org-latex-preview--svg-make-fg-currentColor fragments-to-show) (mapc #'org-latex-preview--svg-make-fg-currentColor fragments-to-show)
(if (plist-get extended-info :place-preview-p) (org-latex-preview--place-images extended-info fragments-to-show))))
(org-latex-preview--place-images extended-info fragments-to-show)
(dolist (fragment-info fragments-to-show)
(org-latex-preview--cache-image
(plist-get fragment-info :key)
(plist-get fragment-info :path)
(org-latex-preview--display-info
extended-info fragment-info)))))))
(defun org-latex-preview--svg-make-fg-currentColor (svg-fragment) (defun org-latex-preview--svg-make-fg-currentColor (svg-fragment)
"Replace the foreground color in SVG-FRAGMENT's file with \"currentColor\". "Replace the foreground color in SVG-FRAGMENT's file with \"currentColor\".
@ -1998,44 +1999,51 @@ EXTENDED-INFO, and displayed in the buffer."
(fragments (plist-get extended-info :fragments)) (fragments (plist-get extended-info :fragments))
fragments-to-show page-info-end) fragments-to-show page-info-end)
(while (search-forward "]" nil t) (while (search-forward "]" nil t)
(setq page-info-end (point)) (setq page-info-end (point))
(save-excursion (save-excursion
(backward-list) (backward-list)
(if (re-search-forward "\\=\\[\\([0-9]+\\) " page-info-end t) (if (re-search-forward "\\=\\[\\([0-9]+\\) " page-info-end t)
(let* ((page (string-to-number (match-string 1))) (let* ((page (string-to-number (match-string 1)))
(fragment-info (nth (1- page) fragments))) (fragment-info (nth (1- page) fragments)))
(plist-put fragment-info :path (plist-put fragment-info :path
(format "%s-%09d.png" outputs-no-ext page)) (format "%s-%09d.png" outputs-no-ext page))
(push fragment-info fragments-to-show))))) (when (plist-get fragment-info :height)
;; geometry has been recorded by latex filter, can display image
(push fragment-info fragments-to-show))))))
(when fragments-to-show (when fragments-to-show
(setq fragments-to-show (nreverse fragments-to-show)) (org-latex-preview--place-images
(if (plist-get extended-info :place-preview-p) extended-info (nreverse fragments-to-show)))))
(org-latex-preview--place-images extended-info fragments-to-show)
(dolist (fragment-info fragments-to-show)
(org-latex-preview--cache-image
(plist-get fragment-info :key)
(plist-get fragment-info :path)
(org-latex-preview--display-info
extended-info fragment-info)))))))
(defun org-latex-preview--place-images (extended-info &optional fragments) (defun org-latex-preview--place-images (extended-info &optional fragments)
"Place images for each of FRAGMENTS, according to their data and EXTENDED-INFO. "Cache and place images for FRAGMENTS, according to their data and EXTENDED-INFO.
Should FRAGMENTS not be explicitly provided, all of the fragments Should FRAGMENTS not be explicitly provided, all of the fragments
listed in EXTENDED-INFO will be used." listed in EXTENDED-INFO will be used.
If this is an export run, images will only be cached, not placed."
(let ((fragments (or fragments (plist-get extended-info :fragments)))) (let ((fragments (or fragments (plist-get extended-info :fragments))))
(with-current-buffer (plist-get extended-info :org-buffer) (if (plist-get extended-info :place-preview-p)
(save-excursion (with-current-buffer (plist-get extended-info :org-buffer)
(cl-loop (save-excursion
for fragment-info in fragments (cl-loop
for image-file = (plist-get fragment-info :path) for fragment-info in fragments
for ov = (plist-get fragment-info :overlay) for image-file = (plist-get fragment-info :path)
do (org-latex-preview--update-overlay for ov = (plist-get fragment-info :overlay)
ov do (unless (overlay-buffer ov)
(org-latex-preview--cache-image (message "Offending overlay for fragment %S" fragment-info))
(plist-get fragment-info :key) do (org-latex-preview--update-overlay
image-file ov
(org-latex-preview--display-info (org-latex-preview--cache-image
extended-info fragment-info)))))))) (plist-get fragment-info :key)
image-file
(org-latex-preview--display-info
extended-info fragment-info))))))
(dolist (fragment-info fragments)
(org-latex-preview--cache-image
(plist-get fragment-info :key)
(plist-get fragment-info :path)
(org-latex-preview--display-info
extended-info fragment-info))))))
(defconst org-latex-preview--cache-name "LaTeX preview cached image data" (defconst org-latex-preview--cache-name "LaTeX preview cached image data"
"The name used for Org LaTeX Preview objects in the org-persist cache.") "The name used for Org LaTeX Preview objects in the org-persist cache.")