]> git.donarmstrong.com Git - lilypond.git/blobdiff - scm/output-svg.scm
Merge branch 'lilypond/translation' of ssh://jomand@git.sv.gnu.org/srv/git/lilypond
[lilypond.git] / scm / output-svg.scm
index 20ce40b230e628dd3b80fdb024ebc4ec77239c0e..7d7a6b343717a07b987642dbe7a359fa0c19fdf7 100644 (file)
@@ -1,21 +1,9 @@
-;;;; output-svg.scm -- implement Scheme output routines for SVG1
+;;;; output-svg.scm -- implement Scheme output routines for SVG
 ;;;;
 ;;;;  source file of the GNU LilyPond music typesetter
 ;;;;
 ;;;; (c) 2002--2009 Jan Nieuwenhuizen <janneke@gnu.org>
-
-;;;; http://www.w3.org/TR/SVG11
-;;;; http://www.w3.org/TR/SVG12/ -- page, pageSet in draft
-
-;;;; TODO:
-;;;;  * .cff MUST NOT be in fc's fontpath.
-;;;;    - workaround: remove mf/out from ~/.fonts.conf,
-;;;;      instead add ~/.fonts and symlink all /mf/out/*otf there.
-;;;;    - bug in fontconfig/freetype/pango?
-
-;;;;  * inkscape page/pageSet support
-;;;;  * inkscape SVG-font support
-;;;;    - use fontconfig/fc-cache for now, see output-gnome.scm
+;;;;                Patrick McCarty <pnorcks@gmail.com>
 
 (define-module (scm output-svg))
 (define this-module (current-module))
 
 (define (dispatch expr)
   (let ((keyword (car expr)))
-    (cond
-     ((eq? keyword 'some-func) "")
-     ;;((eq? keyword 'placebox) (dispatch (cadddr expr)))
-     (else
-      (if (module-defined? this-module keyword)
-         (apply (eval keyword this-module) (cdr expr))
-         (begin
-           (ly:warning (_ "undefined: ~S") keyword)
-           ""))))))
+    (cond ((eq? keyword 'some-func) "")
+         (else (if (module-defined? this-module keyword)
+                   (apply (eval keyword this-module) (cdr expr))
+                   (begin (ly:warning (_ "undefined: ~S") keyword)
+                          ""))))))
 
 ;; Helper functions
 (define-public (attributes attributes-alist)
   (if (equal? string "")
       (apply eoc entity attributes-alist)
       (string-append
-       (apply eo (cons entity attributes-alist)) string (ec entity))))
+       (apply eo (cons entity attributes-alist)) string (ec entity))))
 
 (define (offset->point o)
-  (format " ~S,~S" (car o)  (- (cdr o))))
+  (ly:format "~4f ~4f" (car o) (- (cdr o))))
 
 (define (number-list->point lst)
   (define (helper lst)
     (if (null? lst)
        '()
-       (cons (format "~S,~S" (car lst) (cadr lst))
+       (cons (format "~S ~S" (car lst) (- (cadr lst)))
              (helper (cddr lst)))))
 
   (string-join (helper lst) " "))
   (let* ((c0 (car (list-tail lst 3)))
         (c123 (list-head lst 3)))
     (string-append
-     (if (not close) "M " "L ")
-     (offset->point c0)
-     "C " (apply string-append (map offset->point c123))
-     (if (not close) "" (string-append
-                        "L " (offset->point close))))))
+      (if (not close) "M" "L")
+      (offset->point c0)
+      "C" (string-join (map offset->point c123) " ")
+      (if (not close) "" "z"))))
 
 (define (sqr x)
   (* x x))
   (define alist '())
   (define (set-attribute attr val)
     (set! alist (assoc-set! alist attr val)))
-  (let*
-    ((match-1 (regexp-exec pango-description-regexp-comma str))
-     (match-2 (regexp-exec pango-description-regexp-nocomma str))
-     (match (if match-1
-               match-1
-               match-2)))
+  (let* ((match-1 (regexp-exec pango-description-regexp-comma str))
+        (match-2 (regexp-exec pango-description-regexp-nocomma str))
+        (match (if match-1 match-1 match-2)))
 
     (if (regexp-match? match)
        (begin
       (let* ((dx (car rest))
             (dy (cadr rest))
             (total-x (+ dx next-horiz-adv)))
-       (if (or (not (= 0 (inexact->exact total-x)))
-               (not (= 0 (inexact->exact dy))))
+       (if (or (not (zero? total-x))
+               (not (zero? dy)))
            (let ((x (ly:format "~4f" total-x))
                  (y (ly:format "~4f" dy)))
              (set-attribute 'transform
 ;;
 (define (glyph-element-regexp name)
   (make-regexp (string-append "<glyph"
-                             "(([\r\n\t ]+[-a-z]+=\"[^\"]*\")+)?"
-                             "[\r\n\t ]+glyph-name=\"("
+                             "(([[:space:]]+[-a-z]+=\"[^\"]*\")+)?"
+                             "[[:space:]]+glyph-name=\"("
                              name
                              ")\""
-                             "(([\r\n\t ]+[-a-z]+=\"[^\"]*\")+)?"
-                             "([\r\n\t ]+)?"
+                             "(([[:space:]]+[-a-z]+=\"[^\"]*\")+)?"
+                             "([[:space:]]+)?"
                              "/>")))
 
 (define (extract-glyph all-glyphs name size . rest)
 
 (define (bezier-sandwich lst thick)
   (let* ((first (list-tail lst 4))
-        (first-c0 (car (list-tail first 3)))
         (second (list-head lst 4)))
     (entity 'path ""
            '(stroke-linejoin . "round")
            '(fill . "currentColor")
            `(stroke-width . ,thick)
            `(d . ,(string-append (svg-bezier first #f)
-                                 (svg-bezier second first-c0)))
-           )))
+                                 (svg-bezier second #t))))))
 
 (define (char font i)
   (dispatch
 
 (define (circle radius thick is-filled)
   (entity
-   'circle ""
-   '(stroke-linejoin . "round")
-   '(stroke-linecap . "round")
-   `(fill . ,(if is-filled "currentColor" "none"))
-   `(stroke . "currentColor")
-   `(stroke-width . ,thick)
-   `(r . ,radius)))
+    'circle ""
+    '(stroke-linejoin . "round")
+    '(stroke-linecap . "round")
+    `(fill . ,(if is-filled "currentColor" "none"))
+    `(stroke . "currentColor")
+    `(stroke-width . ,thick)
+    `(r . ,radius)))
 
 (define (dashed-line thick on off dx dy phase)
-  (draw-line thick 0 0 dx dy `(style . ,(format "stroke-dasharray:~a,~a;" on off))))
+  (draw-line thick 0 0 dx dy
+            `(stroke-dasharray . ,(format "~a,~a" on off))))
 
 (define (draw-line thick x1 y1 x2 y2 . alist)
   (apply entity 'line ""
         (append
-         `((stroke-linejoin . "round")
-           (stroke-linecap . "round")
-           (stroke-width . ,thick)
-           (stroke . "currentColor")
-           (x1 . ,x1)
-           (y1 . ,(- y1))
-           (x2 . ,x2)
-           (y2 . ,(- y2)))
-         alist)))
+          `((stroke-linejoin . "round")
+            (stroke-linecap . "round")
+            (stroke-width . ,thick)
+            (stroke . "currentColor")
+            (x1 . ,x1)
+            (y1 . ,(- y1))
+            (x2 . ,x2)
+            (y2 . ,(- y2)))
+          alist)))
 
 (define (ellipse x-radius y-radius thick is-filled)
   (entity
-   'ellipse ""
-   '(stroke-linejoin . "round")
-   '(stroke-linecap . "round")
-   `(fill . ,(if is-filled "currentColor" "none"))
-   `(stroke . "currentColor")
-   `(stroke-width . ,thick)
-   `(rx . ,x-radius)
-   `(ry . ,y-radius)))
+    'ellipse ""
+    '(stroke-linejoin . "round")
+    '(stroke-linecap . "round")
+    `(fill . ,(if is-filled "currentColor" "none"))
+    `(stroke . "currentColor")
+    `(stroke-width . ,thick)
+    `(rx . ,x-radius)
+    `(ry . ,y-radius)))
 
 (define (embedded-svg string)
   string)
 
 (define (oval x-radius y-radius thick is-filled)
   (let ((x-max x-radius)
-        (x-min (- x-radius))
-        (y-max y-radius)
-        (y-min (- y-radius)))
+       (x-min (- x-radius))
+       (y-max y-radius)
+       (y-min (- y-radius)))
     (entity
-     'path ""
-     '(stroke-linejoin . "round")
-     '(stroke-linecap . "round")
-     `(fill . ,(if is-filled "currentColor" "none"))
-     `(stroke . "currentColor")
-     `(stroke-width . ,thick)
-     `(d . ,(ly:format "M~4f,~4f C~4f,~4f  ~4f,~4f ~4f,~4f S~4f,~4f ~4f,~4f"
-               x-max 0
-               x-max y-max
-               x-min y-max
-               x-min 0
-               x-max y-min
-               x-max 0)))))
+      'path ""
+      '(stroke-linejoin . "round")
+      '(stroke-linecap . "round")
+      `(fill . ,(if is-filled "currentColor" "none"))
+      `(stroke . "currentColor")
+      `(stroke-width . ,thick)
+      `(d . ,(ly:format "M~4f ~4fC~4f ~4f ~4f ~4f ~4f ~4fS~4f ~4f ~4f ~4fz"
+                       x-max 0
+                       x-max y-max
+                       x-min y-max
+                       x-min 0
+                       x-max y-min
+                       x-max 0)))))
 
 (define (path thick commands)
   (define (convert-path-exps exps)
     (if (pair? exps)
        (let*
-           ((head (car exps))
-            (rest (cdr exps))
-            (arity
-             (cond
-              ((memq head '(rmoveto rlineto lineto moveto)) 2)
-              ((memq head '(rcurveto curveto)) 6)
-              (else 1)))
-            (args (take rest arity))
-            (svg-head (assoc-get head '((rmoveto . m)
-                                        (rcurveto . c)
-                                        (curveto . C)
-                                        (moveto . M)
-                                        (lineto . L)
-                                        (rlineto . l))
-                                 ""))
-            )
-
-         (cons (format "~a~a "
-                       svg-head (number-list->point args)
-                       )
+         ((head (car exps))
+          (rest (cdr exps))
+          (arity
+            (cond ((memq head '(rmoveto rlineto lineto moveto)) 2)
+                  ((memq head '(rcurveto curveto)) 6)
+                  ((eq? head 'closepath) 0)
+                  (else 1)))
+          (args (take rest arity))
+          (svg-head (assoc-get head
+                               '((rmoveto . m)
+                                 (rcurveto . c)
+                                 (curveto . C)
+                                 (moveto . M)
+                                 (lineto . L)
+                                 (rlineto . l)
+                                 (closepath . z))
+                               "")))
+
+         (cons (format "~a~a" svg-head (number-list->point args))
                (convert-path-exps (drop rest arity))))
        '()))
 
          '(stroke-linecap . "round")
          '(stroke . "currentColor")
          '(fill . "none")
-         `(d . ,(string-join (convert-path-exps commands) " "))))
+         `(d . ,(apply string-append (convert-path-exps commands)))))
 
 (define (placebox x y expr)
   (if (string-null? expr)
 
 (define (polygon coords blot-diameter is-filled)
   (entity
-   'polygon ""
-   '(stroke-linejoin . "round")
-   '(stroke-linecap . "round")
-   `(stroke-width . ,blot-diameter)
-   `(fill . ,(if is-filled "currentColor" "none"))
-   '(stroke . "currentColor")
-   `(points . ,(string-join
-               (map offset->point (ly:list->offsets '() coords))))
-   ))
+    'polygon ""
+    '(stroke-linejoin . "round")
+    '(stroke-linecap . "round")
+    `(stroke-width . ,blot-diameter)
+    `(fill . ,(if is-filled "currentColor" "none"))
+    '(stroke . "currentColor")
+    `(points . ,(string-join
+                 (map offset->point (ly:list->offsets '() coords))))))
+
+(define (repeat-slash width slope thickness)
+  (define (euclidean-length x y)
+    (sqrt (+ (* x x) (* y y))))
+  (let* ((x-width (euclidean-length thickness (/ thickness slope)))
+        (height (* width slope)))
+    (entity
+      'path ""
+      '(fill . "currentColor")
+      `(d . ,(ly:format "M0 0l~4f 0 ~4f ~4f ~4f 0z"
+                       x-width width (- height) (- x-width))))))
 
 (define (resetcolor)
   "</g>\n")
   "</g>\n")
 
 (define (round-filled-box breapth width depth height blot-diameter)
-  (entity 'rect ""
-         ;; The stroke will stick out.  To use stroke,
-         ;; the stroke-width must be subtracted from all other dimensions.
-         ;;'(stroke-linejoin . "round")
-         ;;'(stroke-linecap . "round")
-         ;;`(stroke-width . ,blot)
-         ;;'(stroke . "red")
-         ;;'(fill . "orange")
-
-         `(x . ,(- breapth))
-         `(y . ,(- height))
-         `(width . ,(+ breapth width))
-         `(height . ,(+ depth height))
-         `(ry . ,(/ blot-diameter 2))
-         '(fill . "currentColor")
-         ))
+  (entity
+    'rect ""
+    ;; The stroke will stick out.  To use stroke,
+    ;; the stroke-width must be subtracted from all other dimensions.
+    ;;'(stroke-linejoin . "round")
+    ;;'(stroke-linecap . "round")
+    ;;`(stroke-width . ,blot)
+    ;;'(stroke . "red")
+    ;;'(fill . "orange")
+
+    `(x . ,(- breapth))
+    `(y . ,(- height))
+    `(width . ,(+ breapth width))
+    `(height . ,(+ depth height))
+    `(ry . ,(/ blot-diameter 2))
+    '(fill . "currentColor")))
 
 (define (setcolor r g b)
-  (format "<g color=\"rgb(~a%,~a%,~a%)\">\n"
-         (* 100 r) (* 100 g) (* 100 b)
-         ))
+  (format "<g color=\"rgb(~a%, ~a%, ~a%)\">\n"
+         (* 100 r) (* 100 g) (* 100 b)))
 
 ;; rotate around given point
 (define (setrotation ang x y)
-  (format "<g transform=\"rotate(~a,~a,~a)\">\n"
-    (number->string (* -1 ang))
-    (number->string x)
-    (number->string (* -1 y))))
+  (ly:format "<g transform=\"rotate(~4f, ~4f, ~4f)\">\n"
+            (- ang) x (- y)))
 
 (define (text font string)
   (dispatch `(fontify ,font ,(entity 'tspan (string->entities string)))))