summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/changes.tely25
-rw-r--r--input/regression/markup-line-styles.ly75
-rw-r--r--scm/define-markup-commands.scm81
3 files changed, 178 insertions, 3 deletions
diff --git a/Documentation/changes.tely b/Documentation/changes.tely
index 24e973e4fd..c943a1a64e 100644
--- a/Documentation/changes.tely
+++ b/Documentation/changes.tely
@@ -62,6 +62,31 @@ which scares away people.
@end ignore
@item
+Markup-command @code{\draw-squiggle-line} is now available.
+Customizing is possible with overrides of @code{thickness}, @code{angularity},
+@code{height} and @code{orientation}
+@lilypond[quote,verbatim]
+\markup
+ \overlay {
+ \draw-squiggle-line #0.5 #'(3 . 3) ##t
+
+ \translate #'(3 . 3)
+ \override #'(thickness . 4)
+ \draw-squiggle-line #0.5 #'(3 . -3) ##t
+
+ \translate #'(6 . 0)
+ \override #'(angularity . -5)
+ \draw-squiggle-line #0.5 #'(-3 . -3) ##t
+
+ \translate #'(3 . -3)
+ \override #'(angularity . 2)
+ \override #'(height . 0.3)
+ \override #'(orientation . -1)
+ \draw-squiggle-line #0.2 #'(-3 . 3) ##t
+ }
+@end lilypond
+
+@item
Markup-commands @code{\undertie} and @code{\overtie} are now available, as well
the generic markup-command @code{\tie}.
@lilypond[quote,verbatim]
diff --git a/input/regression/markup-line-styles.ly b/input/regression/markup-line-styles.ly
index ac15fa78ad..aa718e4f5c 100644
--- a/input/regression/markup-line-styles.ly
+++ b/input/regression/markup-line-styles.ly
@@ -1,11 +1,13 @@
\version "2.19.22"
\header {
- texidoc = "The markup-commands @code{\\draw-dashed-line} and
- @code{\\draw-dotted-line} should print the same visual length as
- @code{\\draw-line}."
+ texidoc = "The markup-commands @code{\\draw-dashed-line},
+ @code{\\draw-dotted-line} and @code{\\draw-squiggle-line} should print the
+ same visual length as @code{\\draw-line}.
+ Also testing possible overrides for @code{\\draw-squiggle-line}"
}
+%% draw-dotted-line and draw-dashed-line
test =
#(define-scheme-function (x-nmbr y-nmbr)(number? number?)
(let* ((lst (map
@@ -57,4 +59,71 @@ test =
(iota (abs x-nmbr)))))
lst))
+%% draw-squiggle-line
+mrkp =
+\markup
+ \override #'(word-space . 2)
+ \column {
+ \line { \draw-squiggle-line #0.5 #'(6 . 0) ##t \tiny \vcenter "default" }
+ \line {
+ \override #'(orientation . -1) \draw-squiggle-line #0.5 #'(6 . 0) ##t
+ \tiny \vcenter "different orientation"
+ }
+ \line {
+ \draw-squiggle-line #0.5 #'(6 . 0) ##f
+ \tiny \vcenter "\"eq-end?\" set #f"
+ }
+ \line {
+ \override #'(height . 1) \draw-squiggle-line #0.5 #'(6 . 0) ##t
+ \tiny \vcenter "different height"
+ }
+ \line {
+ \override #'(thickness . 5) \draw-squiggle-line #0.5 #'(6 . 0) ##t
+ \tiny \vcenter "different thickness"
+ }
+ \line {
+ \override #'(angularity . 2) \draw-squiggle-line #0.5 #'(6 . 0) ##t
+ \tiny \vcenter "different angularity"
+ }
+ }
+
+test-draw-squiggle-line =
+#(define-scheme-function (steps) (integer?)
+;; Puts out a markup combining draw-line-markup and draw-squiggle-line-markup
+;; in a helix-like mannor
+ (define (val-pts-list steps)
+ ;; Puts out a list, with each element being a pair of a numerical value
+ ;; and a number-pair
+ ;; The numerical value is used for first-bow-length and its height
+ ;; The number-pair is the destination-point of the line.
+ ;; Those points are on a simple helix around '(0 . 0)
+ (map
+ (lambda (n r)
+ (let* ((y (* (sin n) r))
+ (x (* (cos n) r)))
+ (if (< (abs x) 0.00001)
+ (set! x 0))
+ (if (< (abs y) 0.00001)
+ (set! y 0))
+ (cons (max 0.1 (- 0.5 (/ 1 r))) (cons x y ))))
+ (iota steps 0 (/ TWO-PI steps))
+ (iota steps 3 0.5)))
+
+ (let ((args
+ (map
+ (lambda (arg)
+ #{
+ \markup
+ \combine
+ \draw-line $(cdr arg)
+ \override #`(height . , (car arg))
+ \draw-squiggle-line
+ #(car arg)
+ $(cdr arg) ##f
+ #})
+ (val-pts-list steps))))
+ #{ \markup { \hspace #10 \overlay $args \hspace #5 \vcenter \mrkp } #}))
+
\test #15 #0
+
+\test-draw-squiggle-line #12 #10
diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm
index e22e467f1e..edd70f216d 100644
--- a/scm/define-markup-commands.scm
+++ b/scm/define-markup-commands.scm
@@ -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