]> git.donarmstrong.com Git - lilypond.git/blobdiff - scm/define-markup-commands.scm
Merge branch 'master' into translation
[lilypond.git] / scm / define-markup-commands.scm
index 0ca1042e8df936df77100711ee4831bc7dea6497..edd70f216dc8eaf448987f2e9f81836a4b3f7bd3 100644 (file)
@@ -306,6 +306,87 @@ line-length.
                       new-props
                       (markup #:draw-dashed-line dest))))
 
+(define-markup-command (draw-squiggle-line layout props sq-length dest eq-end?)
+  (number? number-pair? boolean?)
+  #:category graphic
+  #:properties ((thickness 0.5)
+                (angularity 0)
+                (height 0.5)
+                (orientation 1))
+  "
+@cindex drawing squiggled lines within text
+
+A squiggled line.
+
+If @code{eq-end?} is set to @code{#t}, it is ensured the squiggled line ends
+with a bow in same direction as the starting one.  @code{sq-length} is the
+length of the first bow.  @code{dest} is the end point of the squiggled line.
+To match @code{dest} the squiggled line is scaled accordingly.
+Its appearance may be customized by overrides for @code{thickness},
+@code{angularity}, @code{height} and @code{orientation}.
+@lilypond[verbatim,quote]
+\\markup
+  \\column {
+    \\draw-squiggle-line #0.5 #'(6 . 0) ##t
+    \\override #'(orientation . -1)
+    \\draw-squiggle-line #0.5 #'(6 . 0) ##t
+    \\draw-squiggle-line #0.5 #'(6 . 0) ##f
+    \\override #'(height . 1)
+    \\draw-squiggle-line #0.5 #'(6 . 0) ##t
+    \\override #'(thickness . 5)
+    \\draw-squiggle-line #0.5 #'(6 . 0) ##t
+    \\override #'(angularity . 2)
+    \\draw-squiggle-line #0.5 #'(6 . 0) ##t
+  }
+@end lilypond"
+  (let* ((line-thickness (ly:output-def-lookup layout 'line-thickness))
+         (thick (* thickness line-thickness))
+         (x (car dest))
+         (y (cdr dest))
+         (length-to-print (magnitude (make-rectangular x y)))
+         ;; Make a guess how many bows may be needed
+         (guess (max 1 (truncate (/ length-to-print sq-length))))
+         ;; If `eq-end?' is set #t, make sure squiggle-line starts and ends
+         ;; with a bow in same direction
+         (amount (if (and (even? guess) eq-end?) (1+ guess) guess))
+         ;; The lined-up bows needs to fit `length-to-print'
+         ;; Thus scale the length of first bow accordingly
+         ;; Other bows are copies
+         (guessed-squiggle-line-length (* amount sq-length))
+         (line-length-diff (- length-to-print guessed-squiggle-line-length))
+         (line-length-diff-for-each-squiggle
+           (/ line-length-diff amount))
+         (first-bow-length (+ sq-length line-length-diff-for-each-squiggle))
+         ;; Get first bows
+         ;; TODO two bows are created via `make-bow-stencil'
+         ;;      cheaper to use `ly:stencil-scale'?
+         (first-bow-end-coord
+           (cons
+             (/ (* first-bow-length x) length-to-print)
+             (/ (* first-bow-length y) length-to-print)))
+         (init-bow
+           (lambda (o)
+             (make-bow-stencil
+               '(0 . 0)
+               first-bow-end-coord
+               thick angularity height o)))
+         (init-bow-up (init-bow orientation))
+         (init-bow-down (init-bow (- orientation)))
+         ;; Get a list of starting-points for the bows
+         (list-of-starts
+           (map
+             (lambda (n)
+               (cons
+                 (* n (car first-bow-end-coord))
+                 (* n (cdr first-bow-end-coord))))
+             (iota amount))))
+    ;; The final stencil: lined-up bows
+    (apply ly:stencil-add
+      (map
+        (lambda (stil pt) (ly:stencil-translate stil pt))
+        (circular-list init-bow-up init-bow-down)
+        list-of-starts))))
+
 (define-markup-command (draw-hline layout props)
   ()
   #:category graphic
@@ -615,6 +696,95 @@ thickness, and @code{offset} to determine line y-offset.
          (line (make-line-stencil underline-thick x1 y x2 y)))
     (ly:stencil-add m line)))
 
+(define-markup-command (tie layout props arg)
+  (markup?)
+  #:category font
+  #:properties ((thickness 1)
+                (offset 2)
+                (direction UP)
+                (shorten-pair '(0 . 0)))
+  "
+@cindex tie-ing text
+
+Adds a horizontal bow created with @code{make-tie-stencil} at bottom or top
+of @var{arg}.  Looks at @code{thickness} to determine line thickness, and
+@code{offset} to determine y-offset.  The added bow fits the extent of
+@var{arg}, @code{shorten-pair} may be used to modify this.
+@var{direction} may be set using an @code{override} or direction-modifiers or
+@code{voiceOne}, etc.
+
+@lilypond[verbatim,quote]
+\\markup {
+  \\override #'(direction . 1)
+  \\tie \"above\"
+  \\override #'(direction . -1)
+  \\tie \"below\"
+}
+@end lilypond"
+  (let* ((line-thickness (ly:output-def-lookup layout 'line-thickness))
+         (thick (* thickness line-thickness))
+         (stil (interpret-markup layout props arg))
+         (x1 (car (ly:stencil-extent stil X)))
+         (x2 (cdr (ly:stencil-extent stil X)))
+         (y-ext (ly:stencil-extent stil Y))
+         (y (+ (* line-thickness offset direction)
+               ;; we put out zero for positive text-direction, to make it
+               ;; consistent with `underline-markup'
+               ;; TODO: this will be problematic for args like "Eng"
+               ;;       fix it here _and_ in `underline-markup'
+               (if (negative? direction) 0 (cdr y-ext))))
+         (tie
+           (make-tie-stencil
+             (cons (+ x1 (car shorten-pair) line-thickness) y)
+             (cons (- x2 (cdr shorten-pair) line-thickness) y)
+             thick
+             direction)))
+    (ly:stencil-add stil tie)))
+
+(define-markup-command (undertie layout props arg)
+  (markup?)
+  #:category font
+  #:properties (tie-markup)
+  "
+@cindex undertie-ing text
+
+@lilypond[verbatim,quote]
+\\markup \\line {
+  \\undertie \"undertied\"
+  \\override #'(offset . 5)
+  \\override #'(thickness . 1)
+  \\undertie \"undertied\"
+  \\override #'(offset . 1)
+  \\override #'(thickness . 5)
+  \\undertie \"undertied\"
+}
+@end lilypond"
+  (interpret-markup layout (prepend-alist-chain 'direction DOWN props)
+    (make-tie-markup arg)))
+
+(define-markup-command (overtie layout props arg)
+  (markup?)
+  #:category font
+  #:properties (tie-markup)
+  "
+@cindex overtie-ing text
+
+Overtie @var{arg}.
+
+@lilypond[verbatim,quote]
+\\markup \\line {
+  \\overtie \"overtied\"
+  \\override #'(offset . 5)
+  \\override #'(thickness . 1)
+  \\overtie \"overtied\"
+  \\override #'(offset . 1)
+  \\override #'(thickness . 5)
+  \\overtie \"overtied\"
+}
+@end lilypond"
+  (interpret-markup layout (prepend-alist-chain 'direction UP props)
+    (make-tie-markup arg)))
+
 (define-markup-command (box layout props arg)
   (markup?)
   #:category font
@@ -729,8 +899,9 @@ Rotate object with @var{ang} degrees around its center.
 
 Provide a white background for @var{arg}.  The shape of the white
 background is determined by @code{style}.  The default
-is @code{box} which produces a white rectangle.  @code{outline}
-approximates the outline of the markup.
+is @code{box} which produces a rectangle.  @code{rounded-box}
+produces a rounded rectangle.  @code{outline} approximates the
+outline of the markup.
 
 @lilypond[verbatim,quote]
 \\markup {
@@ -739,6 +910,13 @@ approximates the outline of the markup.
     \\override #'(thickness . 1.5)
     \\whiteout whiteout-box
 }
+\\markup {
+  \\combine
+    \\filled-box #'(-1 . 24) #'(-3 . 4) #1
+    \\override #'(style . rounded-box)
+    \\override #'(thickness . 3)
+    \\whiteout whiteout-rounded-box
+}
 \\markup {
   \\combine
     \\filled-box #'(-1 . 18) #'(-3 . 4) #1
@@ -1405,11 +1583,13 @@ equivalent to @code{\"fi\"}.
 @end lilypond"
   (define (concat-string-args arg-list)
     (fold-right (lambda (arg result-list)
-                  (let ((result (if (pair? result-list)
-                                    (car result-list)
-                                    '())))
-                    (if (and (pair? arg) (eqv? (car arg) simple-markup))
-                        (set! arg (cadr arg)))
+                  (let ((result (and (pair? result-list)
+                                     (car result-list))))
+                    (cond ((not (pair? arg)))
+                          ((eq? (car arg) simple-markup)
+                           (set! arg (cadr arg)))
+                          ((eq? (car arg) char-markup)
+                           (set! arg (ly:wide-char->utf-8 (cadr arg)))))
                     (if (and (string? result) (string? arg))
                         (cons (string-append arg result) (cdr result-list))
                         (cons arg result-list))))
@@ -2242,12 +2422,9 @@ returns an empty markup.
   (procedure? markup?)
   #:category other
   "Apply the @var{procedure} markup command to @var{arg}.
-@var{procedure} should take a single argument."
-  (let ((anonymous-with-signature (lambda (layout props arg) (procedure layout props arg))))
-    (set-object-property! anonymous-with-signature
-                          'markup-signature
-                          (list markup?))
-    (interpret-markup layout props (list anonymous-with-signature arg))))
+@var{procedure} takes the same arguments as @code{interpret-markup}
+and returns a stencil."
+  (procedure layout props arg))
 
 (define-markup-command (footnote layout props mkup note)
   (markup? markup?)
@@ -3447,9 +3624,12 @@ A feta brace in point size @var{size}, rotated 180 degrees.
 
 Construct a note symbol, with stem and flag.  By using fractional values for
 @var{dir}, longer or shorter stems can be obtained.
-Supports all note-head-styles.
+Supports all note-head-styles.  Ancient note-head-styles will get
+mensural-style-flags.  @code{flag-style} may be overridden independently.
 Supported flag-styles are @code{default}, @code{old-straight-flag},
-@code{modern-straight-flag} and @code{flat-flag}.
+@code{modern-straight-flag}, @code{flat-flag}, @code{mensural} and
+@code{neomensural}.  The latter two flag-styles will both result in
+mensural-flags.  Both are supplied for convenience.
 
 @lilypond[verbatim,quote]
 \\markup {
@@ -3460,7 +3640,8 @@ Supported flag-styles are @code{default}, @code{old-straight-flag},
 @end lilypond"
   (define (get-glyph-name-candidates dir log style)
     (map (lambda (dir-name)
-           (format #f "noteheads.~a~a" dir-name
+           (format #f "noteheads.~a~a"
+                   dir-name
                    (if (and (symbol? style)
                             (not (equal? 'default style)))
                        (select-head-glyph style (min log 2))
@@ -3546,7 +3727,9 @@ Supported flag-styles are @code{default}, @code{old-straight-flag},
                                  (sign dir) log 'default))
                 result)))
          (head-glyph (ly:font-get-glyph font head-glyph-name))
-         (ancient-flags? (or (eq? style 'mensural) (eq? style 'neomensural)))
+         (ancient-flags?
+           (member style
+                   '(mensural neomensural petrucci semipetrucci blackpetrucci)))
          (attach-indices (ly:note-head::stem-attachment font head-glyph-name))
          (stem-length (* size-factor (max 3 (- log 1))))
          ;; With ancient-flags we want a tighter stem
@@ -3562,7 +3745,10 @@ Supported flag-styles are @code{default}, @code{old-straight-flag},
                                (cdr attach-indices)))))
          ;; For a tighter stem (with ancient-flags) the stem-width has to be
          ;; adjusted.
-         (stem-X-corr (if ancient-flags? (* 0.5 dir stem-thickness) 0))
+         (stem-X-corr
+           (if (or ancient-flags?
+                   (member flag-style '(mensural neomensural)))
+                   (* 0.5 dir stem-thickness) 0))
          (stem-glyph (and (> log 0)
                           (ly:round-filled-box
                            (ordered-cons (+ stem-X-corr (car attach-off))
@@ -3600,11 +3786,15 @@ Supported flag-styles are @code{default}, @code{old-straight-flag},
                               flat-flag)
                              (else
                               (ly:font-get-glyph font
-                                                 (format #f (if ancient-flags?
-                                                                "flags.mensural~a2~a"
-                                                                "flags.~a~a")
-                                                         (if (> dir 0) "u" "d")
-                                                         log))))
+                                (format #f
+                                        (if (or (member flag-style
+                                                        '(mensural neomensural))
+                                                (and ancient-flags?
+                                                     (null? flag-style)))
+                                            "flags.mensural~a2~a"
+                                            "flags.~a~a")
+                                        (if (> dir 0) "u" "d")
+                                        log))))
                        (cons (+ (car attach-off)
                                 ;; For tighter stems (with ancient-flags) the
                                 ;; flag has to be adjusted different.