]> git.donarmstrong.com Git - lilypond.git/blobdiff - scm/flag-styles.scm
Merge commit 'origin' into beamlets2
[lilypond.git] / scm / flag-styles.scm
index 4a6db49d13c5c5d73e403901193c690317949dd0..ae671db8ba25d24221012fdb5532548b4e47d66c 100644 (file)
@@ -2,6 +2,10 @@
 ;;;;
 ;;;;  source file of the GNU LilyPOnd music typesetter
 ;;;;
+;;;;  This file implements different flag styles in Scheme / GUILE, most
+;;;;  notably the old-straight-flag and the modern-straight-flag styles.
+;;;;
+
 
 (define-public (no-flag stem-grob)
   "No flag: Simply return empty stencil"
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
-;; ;; TODO
-;; (define-public (add-stroke-straight stencil dir stroke-style)
-;;   stencil
-;; )
-;;
-;; ;; Create a stencil for a straight flag
-;; ;; flag-thickness, -spacing are given in staff spaces
-;; ;; *flag-length are given in black notehead widths
-;; ;; TODO
-;; (define-public (straight-flag flag-thickness flag-spacing
-;;                        upflag-angle upflag-length
-;;                        downflag-angle downflag-length)
-;;   (lambda (stem-grob)
-;;     (let* ((log (ly:grob-property stem-grob 'duration-log))
-;;            (staff-space 1) ; TODO
-;;            (black-notehead-width 1) ; TODO
-;;            (stem-thickness 1) ; TODO: get rid of
-;;            (half-stem-thickness (/ stem-thickness 2))
-;;            (staff-space 1) ; TODO
-;;            (up-length (+ (* upflag-length black-notehead-width) half-stem-thickness))
-;;            (down-length (+ (* downflag-length black-notehead-width) half-stem-thickness))
-;;            (thickness (* flag-thickness staff-space))
-;;            (spacing (* flag-spacing staff-space)))
-;;       empty-stencil
-;;     )
-;;   )
-;; )
-;;
-;; ;; Modern straight flags: angles are not so large as with the old style
-;; (define-public (modern-straight-flag stem-grob)
-;;   ((straight-flag 0.55 0.9 -18 0.95 22 1.0) stem-grob))
-;;
-;; ;; Old-straight flags (Bach, etc.): quite large flag angles
-;; (define-public (old-straight-flag stem-grob)
-;;   ((straight-flag 0.55 0.9 -45 0.95 45 1.0) stem-grob))
+(define-public (add-stroke-straight stencil stem-grob dir log stroke-style offset length thickness stroke-thickness)
+  "Add the stroke for acciaccatura to the given flag stencil.
+  The stroke starts for up-flags at upper-end-of-flag+(0,length/2) and 
+  ends at (0, vertical-center-of-flag-end) - (flag-x-width/2, flag-x-width + flag-thickness).
+  Here length is the whole length, while flag-x-width is just the 
+  x-extent and thus depends on the angle! Other combinations don't look as 
+  good... For down-stems the y-coordinates are simply mirrored."
+  (let* ((start (offset-add offset (cons 0  (* (/ length 2) dir))))
+         (end (offset-add (cons 0 (cdr offset)) 
+                          (cons (- (/ (car offset) 2)) (* (- (+ thickness (car offset))) dir))))
+         (stroke (make-line-stencil stroke-thickness (car start) (cdr start) (car end) (cdr end))))
+  (ly:stencil-add stencil stroke)))
+
+(define PI-OVER-180  (/ (atan 1 1) 45))
+(define (degrees->radians angle-degrees)
+  "Convert the given angle from degrees to radians"
+  (* angle-degrees PI-OVER-180))
+
+(define (polar->rectangular radius angle-in-degrees)
+  "Convert polar coordinate @code{radius} and @code{angle-in-degrees}
+   to (x-length . y-length)"
+  (let* ((complex (make-polar
+                    radius
+                    (degrees->radians angle-in-degrees))))
+     (cons
+       (real-part complex)
+       (imag-part complex))))
+
+(define (buildflag flag-stencil remain curr-stencil spacing)
+  "Internal function to recursively create a stencil with @code{remain} flags
+   from the single-flag stencil curr-stencil, which is already translated to
+   the position of the previous flag position."
+  (if (> remain 0)
+      (let* ((translated-stencil (ly:stencil-translate-axis curr-stencil spacing Y))
+             (new-stencil (ly:stencil-add flag-stencil translated-stencil)))
+        (buildflag new-stencil (- remain 1) translated-stencil spacing))
+      flag-stencil))
+
+(define-public (straight-flag flag-thickness flag-spacing
+                       upflag-angle upflag-length
+                       downflag-angle downflag-length)
+    "Create a stencil for a straight flag.
+     flag-thickness, -spacing are given in staff spaces,
+     *flag-angle is given in degree, *flag-length is given in staff spaces. 
+     All lengths will be scaled according to the font size of the note."
+  (lambda (stem-grob)
+    (let* ((log (ly:grob-property stem-grob 'duration-log))
+           (dir (ly:grob-property stem-grob 'direction))
+           (stem-up (eqv? dir UP))
+           (layout (ly:grob-layout stem-grob))
+           ; scale with the note size (e.g. for grace notes)
+           (factor (magstep (ly:grob-property stem-grob 'font-size 0)))
+           (grob-stem-thickness (ly:grob-property stem-grob 'thickness))
+           (line-thickness (ly:output-def-lookup layout 'line-thickness))
+           (half-stem-thickness (/ (* grob-stem-thickness line-thickness) 2))
+           (raw-length (if stem-up upflag-length downflag-length))
+           (angle (if stem-up upflag-angle downflag-angle))
+           (flag-length (+ (* raw-length factor) half-stem-thickness))
+           (flag-end (polar->rectangular flag-length angle))
+           (thickness (* flag-thickness factor))
+           (thickness-offset (cons 0 (* -1 thickness dir)))
+           (spacing (* -1 flag-spacing factor dir ))
+           (start (cons (- half-stem-thickness) (* half-stem-thickness dir)))
+           ; The points of a round-filled-polygon need to be given in clockwise
+           ; order, otherwise the polygon will be enlarged by blot-size*2!
+           (points (if stem-up (list start flag-end
+                                     (offset-add flag-end thickness-offset)
+                                     (offset-add start thickness-offset))
+                               (list start
+                                     (offset-add start thickness-offset)
+                                     (offset-add flag-end thickness-offset)
+                                     flag-end)))
+           (stencil (ly:round-filled-polygon points half-stem-thickness))
+           ; Log for 1/8 is 3, so we need to subtract 3
+           (flag-stencil (buildflag stencil (- log 3) stencil spacing))
+           (stroke-style (ly:grob-property stem-grob 'stroke-style)))
+    (if (equal? stroke-style "grace")
+      (add-stroke-straight flag-stencil stem-grob
+                           dir log
+                           stroke-style
+                           flag-end flag-length
+                           thickness
+                           (* half-stem-thickness 2))
+      flag-stencil))))
+
+(define-public (modern-straight-flag stem-grob)
+  "Modern straight flag style (for composers like Stockhausen, Boulez, etc.).
+   The angles are 18 and 22 degrees and thus smaller than for the ancient style
+   of Bach etc."
+  ((straight-flag 0.55 1 -18 1.1 22 1.2) stem-grob))
+
+(define-public (old-straight-flag stem-grob)
+  "Old straight flag style (for composers like Bach). The angles of the flags
+   are both 45 degrees."
+  ((straight-flag 0.55 1 -45 1.2 45 1.4) stem-grob))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                tmpstencil)))
       (if (ly:stencil-empty? stroke-stencil)
         (begin
-          (ly:warning (_ "flag stroke `~a' or `~a'not found") font-char alt-font-char)
+          (ly:warning (_ "flag stroke `~a' or `~a' not found") font-char alt-font-char)
           stencil)
         (ly:stencil-add stencil stroke-stencil)))))