X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scm%2Foutput-svg.scm;h=e99711f9c6e054ee99accb86a0cad5e4cf50983f;hb=797245ff520d9c44f0308bbc2828bb4747c84123;hp=ab6ec5a6e206c8dab060546119995f4bd26e449a;hpb=51af9db63bb975c9b00af933b8ba3b433d5f7d41;p=lilypond.git diff --git a/scm/output-svg.scm b/scm/output-svg.scm index ab6ec5a6e2..e99711f9c6 100644 --- a/scm/output-svg.scm +++ b/scm/output-svg.scm @@ -2,7 +2,7 @@ ;;;; ;;;; source file of the GNU LilyPond music typesetter ;;;; -;;;; (c) 2002--2006 Jan Nieuwenhuizen +;;;; (c) 2002--2009 Jan Nieuwenhuizen ;;;; http://www.w3.org/TR/SVG11 ;;;; http://www.w3.org/TR/SVG12/ -- page, pageSet in draft @@ -23,9 +23,13 @@ (use-modules (guile) (ice-9 regex) + (ice-9 format) (lily) + (srfi srfi-1) (srfi srfi-13)) +(define fancy-format format) +(define format ergonomic-simple-format) (define lily-unit-length 1.75) @@ -44,20 +48,20 @@ ;; Helper functions (define-public (attributes attributes-alist) (apply string-append - (map (lambda (x) (format #f " ~s=\"~a\"" (car x) (cdr x))) + (map (lambda (x) (format " ~s=\"~a\"" (car x) (cdr x))) attributes-alist))) (define-public (eo entity . attributes-alist) "o = open" - (format #f "<~S~a>\n" entity (attributes attributes-alist))) + (format "<~S~a>\n" entity (attributes attributes-alist))) (define-public (eoc entity . attributes-alist) " oc = open/close" - (format #f "<~S~a/>\n" entity (attributes attributes-alist))) + (format "<~S~a/>\n" entity (attributes attributes-alist))) (define-public (ec entity) "c = close" - (format #f "\n" entity)) + (format "\n" entity)) @@ -68,7 +72,17 @@ (apply eo (cons entity attributes-alist)) string (ec entity)))) (define (offset->point o) - (format #f " ~S,~S" (car o) (- (cdr o)))) + (format " ~S,~S" (car o) (- (cdr o)))) + +(define (number-list->point lst) + (define (helper lst) + (if (null? lst) + '() + (cons (format "~S,~S" (car lst) (cadr lst)) + (helper (cddr lst))))) + + (string-join (helper lst) " ")) + (define (svg-bezier lst close) (let* ((c0 (car (list-tail lst 3))) @@ -84,7 +98,7 @@ (* x x)) (define (integer->entity integer) - (format #f "&#x~x;" integer)) + (fancy-format "&#x~x;" integer)) (define (char->entity char) (integer->entity (char->integer char))) @@ -93,77 +107,64 @@ (apply string-append (map (lambda (x) (char->entity x)) (string->list string)))) +(define svg-element-regexp + (make-regexp "^(<[a-z]+) (.*>)")) + (define pango-description-regexp-comma - (make-regexp "^([^,]+), ?([-a-zA-Z_]*) ([0-9.]+)$")) + (make-regexp ",( Bold)?( Italic)?( Small-Caps)? ([0-9.]+)$")) (define pango-description-regexp-nocomma - (make-regexp "^([^ ]+) ([-a-zA-Z_]*) ?([0-9.]+)$")) + (make-regexp "( Bold)?( Italic)?( Small-Caps)? ([0-9.]+)$")) -(define (pango-description-to-svg-font str) +(define (pango-description-to-svg-font str expr) + (define alist '()) + (define (set-attribute attr val) + (set! alist (assoc-set! alist attr val))) (let* - ((size 4.0) - (family "Helvetica") - (style #f) - (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))) + ((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 - (set! family (match:substring match 1)) - (if (< 0 (string-length (match:substring match 2))) - (set! style (match:substring match 2))) - (set! size - (string->number (match:substring match 3)))) - - (ly:warning (_ "can't decypher Pango description: ~a") str)) - - (set! style - (if (string? style) - (format "font-style:~a;" style) - "")) - - (format "font-family:~a;~afont-size:~a;text-anchor:west" - family - style - (/ size lily-unit-length)) - )) - -;;; FONT may be font smob, or pango font string -(define (svg-font font) - (if (string? font) - (pango-description-to-svg-font font) - (let ((name-style (font-name-style font)) - (size (modified-font-metric-font-scaling font)) - (anchor "west")) - - (format #f "font-family:~a;font-style:~a;font-size:~a;text-anchor:~a;" - (car name-style) (cadr name-style) - size anchor)))) + (set-attribute 'font-family (match:prefix match)) + (if (string? (match:substring match 1)) + (set-attribute 'font-weight "bold")) + (if (string? (match:substring match 2)) + (set-attribute 'font-style "italic")) + (if (string? (match:substring match 3)) + (set-attribute 'font-variant "small-caps")) + (set-attribute 'font-size + (/ (string->number (match:substring match 4)) + lily-unit-length)) + (set-attribute 'text-anchor "start") + (set-attribute 'fill "currentColor")) + (ly:warning (_ "cannot decypher Pango description: ~a") str)) + + (apply entity 'text expr (reverse! alist)))) + +(define (font-smob-to-svg-font font expr) + (let ((name-style (font-name-style font)) + (size (modified-font-metric-font-scaling font))) + + (entity 'text expr + ;; FIXME: The cdr of `name-style' cannot select the + ;; correct SVG font, so we ignore this information for now + `(font-family . ,(car name-style)) + `(font-size . ,size) + '(text-anchor . "start")))) (define (fontify font expr) - (entity 'text expr - `(style . ,(svg-font font)) - '(fill . "currentColor") - )) + (if (string? font) + (pango-description-to-svg-font font expr) + (font-smob-to-svg-font font expr))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; stencil outputters ;;; -;;; catch-all for missing stuff -;;; comment this out to see find out what functions you miss :-) - -(if #f - (begin - (define (dummy . foo) "") - (map (lambda (x) (module-define! this-module x dummy)) - (append - (ly:all-stencil-expressions) - (ly:all-output-backend-commands))) - )) (define (url-link url x y) (string-append @@ -193,19 +194,54 @@ (entity 'path "" '(stroke-linejoin . "round") '(stroke-linecap . "round") - `(stroke-width . ,thick) '(stroke . "currentColor") '(fill . "currentColor") + `(stroke-width . ,thick) `(d . ,(string-append (svg-bezier first #f) (svg-bezier second first-c0))) ))) +(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) + ) + (convert-path-exps (drop rest arity)))) + '())) + + (entity 'path "" + `(stroke-width . ,thick) + '(stroke-linejoin . "round") + '(stroke-linecap . "round") + '(stroke . "currentColor") + '(fill . "none") + `(d . ,(string-join (convert-path-exps commands) " ")))) + (define (char font i) (dispatch `(fontify ,font ,(entity 'tspan (char->entity (integer->char i)))))) (define-public (comment s) - (string-append "\n")) + (string-append "\n")) (define (draw-line thick x1 y1 x2 y2 . alist) @@ -221,7 +257,7 @@ (y2 . ,(- y2))) alist))) -(define (dashed-line thick on off dx dy) +(define (dashed-line thick on off dx dy phase) (draw-line thick 0 0 dx dy `(style . ,(format "stroke-dasharray:~a,~a;" on off)))) (define (named-glyph font name) @@ -231,13 +267,21 @@ (ly:font-glyph-name-to-charcode font name)))))) (define (placebox x y expr) - (entity 'g - - ;; FIXME -- JCN - ;;(dispatch expr) - expr - `(transform . ,(format #f "translate(~f, ~f)" - x (- y))))) + (if (not (string-null? expr)) + (let* + ((match (regexp-exec svg-element-regexp expr)) + (tagname (match:substring match 1)) + (attributes (match:substring match 2))) + + (string-append tagname + ;; FIXME: Not using GNU coding standards + ;; [translate ()] here to work around a + ;; bug in Microsoft Internet Explorer 6.0 + (ly:format " transform=\"translate(~f, ~f)\" " + x (- y)) + attributes + "\n")) + "")) (define (polygon coords blot-diameter is-filled) (entity @@ -251,6 +295,16 @@ (map offset->point (ly:list->offsets '() coords)))) )) +;; rotate around given point +(define (setrotation ang x y) + (format "\n" + (number->string (* -1 ang)) + (number->string x) + (number->string (* -1 y)))) + +(define (resetrotation ang x y) + "\n") + (define (round-filled-box breapth width depth height blot-diameter) (entity 'rect "" ;; The stroke will stick out. To use stroke, @@ -266,6 +320,7 @@ `(width . ,(+ breapth width)) `(height . ,(+ depth height)) `(ry . ,(/ blot-diameter 2)) + '(fill . "currentColor") )) (define (circle radius thick is-filled) @@ -278,18 +333,50 @@ `(stroke-width . ,thick) `(r . ,radius))) +(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))) + +(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))) + (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))))) + (define (text font string) (dispatch `(fontify ,font ,(entity 'tspan (string->entities string))))) (define (utf-8-string pango-font-description string) (dispatch `(fontify ,pango-font-description ,(entity 'tspan string)))) - +(define (embedded-svg string) + string) (define (setcolor r g b) - (format "" + (format "\n" (* 100 r) (* 100 g) (* 100 b) )) (define (resetcolor) - "") + "\n")