|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
;; esvg-build.el. -*- lexical-binding: nil; -*-
;; This file:
;; https://anggtwu.net/elisp/esvg-build.el.html
;; https://anggtwu.net/elisp/esvg-build.el
;; (find-angg "elisp/esvg-build.el")
;; Author: Eduardo Ochs <eduardoochs@gmail.com>
;; Version: 2026aug13
;;
;; This is the fourth lowest-level file in esvg - edrx's (REPL for) SVG.
;;
;; It implements my functions that build SVG objects. Note that
;; `svg-rectangle' builds an SVG object, calls `svg--append' to append
;; it to a certain top-level SVG object, and then runs
;; `svg-possibly-update-image'. In contrast, `esvg-rectangle' just
;; builds an SVG object; appending and updating the image are done
;; elsewhere.
;;
;; (defun e () (interactive) (find-angg "elisp/esvg-build.el"))
;; (defun o () (interactive) (find-angg "elisp/2026-esvg.el"))
;; (defun o () (interactive) (find-angg "elisp/2026-esvg-objects.el"))
;;
;; «.esvg-translate» (to "esvg-translate")
;; «.esvg-flatten» (to "esvg-flatten")
;; «.esvg-make-simple» (to "esvg-make-simple")
(require 'esvg-show) ; (find-angg "elisp/esvg-show.el")
(require 'esvg-eepitch) ; (find-angg "elisp/esvg-eepitch.el")
(require 'esvg-append) ; (find-angg "elisp/esvg-append.el")
;; «esvg-translate» (to ".esvg-translate")
;; Based on: (find-angg "elisp/2026-esvg.el" "esvg-translate")
;; Tests: (esvg-translate-1 '(:a 1 :b 2 foo bar))
;; (esvg-translate :a 1 :b 2 'foo 'bar)
;; (esvg-translate-el :a 1 :b 2 '(:c 3 foo bar))
;;
(defun esvg-translate-1 (list)
(let (attrs)
(while (keywordp (car list))
(let* ((key (intern (substring (symbol-name (car list)) 1)))
(val (cadr list)))
(push `(,key . ,val) attrs)
(setq list (cddr list))))
`(,(reverse attrs) ,@list)))
(defun esvg-expand-last (list) (append (butlast list) (car (last list))))
(defun esvg-translate (&rest args) (esvg-translate-1 args))
(defun esvg-translate-el (&rest args) (esvg-translate-1 (esvg-expand-last args)))
;; «esvg-flatten» (to ".esvg-flatten")
;; svg.el expects the lists of points for polylines and polygons to be
;; lists of dotted pairs; here we also accepts other formats. See:
;; (find-efile "svg.el" "(svg-polyline svg '((200 . 100) ")
;; (find-efile "svg.el" "(defun svg-polyline " "mapconcat")
;; (find-angg "elisp/2026-esvg.el" "esvg-flatten")
;;
(defvar esvg-flattened)
(defun esvg-flattened-add (o)
"A recursive function used by `esvg-flatten-to-list'."
(cond ((null o))
((atom o) (push o esvg-flattened))
(t (esvg-flattened-add (car o))
(esvg-flattened-add (cdr o)))))
;; Test: (esvg-flatten-to-list '(1 2 (3 . "4")))
(defun esvg-flatten-to-list (o)
(setq esvg-flattened nil)
(esvg-flattened-add o)
(reverse esvg-flattened))
;; Test: (esvg-flatten-points '(1 2 (3 . "4")))
(defun esvg-flatten-points (o)
(if (stringp o) o
(let* ((ns (esvg-flatten-to-list o))
(xys (cl-loop for (x y) on ns by 'cddr
collect (format "%s %s" x y))))
(mapconcat 'identity xys ", "))))
;; «esvg-make-simple» (to ".esvg-make-simple")
;; Based on: (find-efunction 'svg-rectangle)
;; (find-efunction 'svg-circle)
;; (find-efunction 'svg-ellipse)
;; (find-efunction 'svg-line)
;; (find-efunction 'svg-polyline)
;; (find-efunction 'svg-polygon)
;; Tests: (esvg-rectangle 1 2 3 4 :foo "red")
;; (esvg-circle 1 2 3 :foo "red")
;; (esvg-elipse 1 2 3 4 :foo "red")
;; (esvg-line 1 2 3 4 :foo "red")
;; (esvg-polyline "1 2 3 4 5 6" :foo "red")
;; (esvg-polygon "1 2 3 4 5 6" :foo "red")
;; (esvg-polyline '((1 . 2) (3 . 4) (5 . 6)) :foo "red")
;; (esvg-polygon '((1 . 2) (3 . 4) (5 . 6)) :foo "red")
;;
(defun esvg-rectangle (x y width height &rest rest)
`(rect ,@(esvg-translate-el :x x :y y :width width :height height rest)))
(defun esvg-circle (cx cy r &rest rest)
`(circle ,@(esvg-translate-el :cx cx :cy cy :r r rest)))
(defun esvg-ellipse (cx cy rx ry rest)
`(ellipse ,@(esvg-translate-el :cx cx :cy cy :rx rx :ry ry rest)))
(defun esvg-line (x1 y1 x2 y2 &rest rest)
`(line ,@(esvg-translate-el :x1 x1 :y1 y1 :x2 x2 :y2 y2 rest)))
(defun esvg-polyline (points &rest rest)
`(polyline ,@(esvg-translate-el :points (esvg-flatten-points points) rest)))
(defun esvg-polygon (points &rest rest)
`(polygon ,@(esvg-translate-el :points (esvg-flatten-points points) rest)))
;; New:
(defun esvg-g (&rest rest)
`(g ,@(esvg-translate-el rest)))
(defun esvg-clippath (&rest rest)
`(clipPath ,@(esvg-translate-el rest)))
(provide 'esvg-append)
;; Local Variables:
;; coding: utf-8-unix
;; End: