;; The final stencil: lined-up bows
(apply ly:stencil-add
(map
- (lambda (stil pt) (ly:stencil-translate stil pt))
+ ly:stencil-translate
(circular-list init-bow-up init-bow-down)
list-of-starts))))
(cons arg result-list))))
'()
arg-list))
-
- (interpret-markup layout
- (prepend-alist-chain 'word-space 0 props)
- (make-line-markup
- (make-override-lines-markup-list
- (cons 'word-space
- (chain-assoc-get 'word-space props))
- (if (markup-command-list? args)
- args
- (concat-string-args args))))))
+ (stack-stencil-line 0
+ (interpret-markup-list layout props
+ (if (markup-command-list? args)
+ args
+ (concat-string-args args)))))
(define (wordwrap-stencils stencils
justify base-space line-width text-dir)
`(delay-stencil-evaluation ,(delay expr))
x y))))
+(define-markup-command (with-outline layout props outline arg)
+ (markup? markup?)
+ #:category other
+ "
+Print @var{arg} with the outline and dimensions of @var{outline}."
+ (ly:stencil-outline (interpret-markup layout props arg)
+ (interpret-markup layout props outline)))
+
+(define-markup-command (with-dimensions-from layout props arg1 arg2)
+ (markup? markup?)
+ #:category other
+ "
+Print @var{arg2} with the dimensions of @var{arg1}."
+ (let* ((stil1 (interpret-markup layout props arg1))
+ (x (ly:stencil-extent stil1 0))
+ (y (ly:stencil-extent stil1 1)))
+ (interpret-markup layout props (markup #:with-dimensions x y arg2))))
+
(define-markup-command (pad-around layout props amount arg)
(number? markup?)
#:category align
}
}
@end lilypond"
- (let* ((m (interpret-markup layout props arg))
- (x (ly:stencil-extent m X))
- (y (ly:stencil-extent m Y)))
- (ly:make-stencil (list 'transparent-stencil (ly:stencil-expr m)) x y)))
+ (ly:stencil-outline empty-stencil (interpret-markup layout props arg)))
(define-markup-command (pad-to-box layout props x-ext y-ext arg)
(number-pair? number-pair? markup?)
#:category music
"@var{glyph-name} is converted to a musical symbol; for example,
@code{\\musicglyph #\"accidentals.natural\"} selects the natural sign from
-the music font. See @ruser{The Feta font} for a complete listing of
+the music font. See @ruser{The Emmentaler font} for a complete listing of
the possible glyphs.
@lilypond[verbatim,quote]
(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 (if (= angle 0)
- (cons flag-length (* half-stem-thickness dir))
- (polar->rectangular flag-length angle)))
+ (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)))
- (points (list start
- flag-end
- (offset-add flag-end thickness-offset)
- (offset-add start thickness-offset)))
+ (raw-points
+ (list
+ '(0 . 0)
+ flag-end
+ (offset-add flag-end thickness-offset)
+ thickness-offset))
+ (points (map (lambda (coord) (offset-add coord start)) raw-points))
(stencil (ly:round-filled-polygon points half-stem-thickness))
;; Log for 1/8 is 3, so we need to subtract 3
(flag-stencil (buildflags stencil (- log 3) stencil spacing)))
(let* ((font (ly:paper-get-font layout (cons '((font-encoding . fetaMusic)
(font-name . #f))
props)))
+ ;; default for text-font-size is 11
+ ;; hence we use (/ text-font-size 11) later, to ensure proper scaling
+ ;; of stem-length and thickness
+ (text-font-size (ly:output-def-lookup layout 'text-font-size 11))
(size-factor (magstep font-size))
(blot (ly:output-def-lookup layout 'blot-diameter))
(head-glyph-name
(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
- (stem-thickness (* size-factor (if ancient-flags? 0.1 0.13)))
- (stemy (* dir stem-length))
+ (stem-thickness
+ (* size-factor (/ text-font-size 11) (if ancient-flags? 0.1 0.13)))
+ (stemy (* dir (/ text-font-size 11) stem-length))
(attach-off (cons (interval-index
(ly:stencil-extent head-glyph X)
(* (sign dir) (car attach-indices)))
stem-thickness
0))
(+ stemy flag-style-Y-corr))))))
-
;; If there is a flag on an upstem and the stem is short, move the dots
;; to avoid the flag. 16th notes get a special case because their flags
;; hang lower than any other flags.
"Like @code{\\override}, for markup lists."
(interpret-markup-list layout (cons (list new-prop) props) args))
+(define-markup-list-command (table layout props column-align lst)
+ (number-list? markup-list?)
+ #:properties ((padding 0)
+ (baseline-skip))
+ "@cindex creating a table.
+
+Returns a table.
+
+@var{column-align} specifies how each column is aligned, possible values are
+-1, 0, 1. The number of elements in @var{column-align} determines how many
+columns will be printed.
+The entries to print are given by @var{lst}, a markup-list. If needed, the last
+row is filled up with @code{point-stencil}s.
+Overriding @code{padding} may be used to increase columns horizontal distance.
+Overriding @code{baseline-skip} to increase rows vertical distance.
+@lilypond[verbatim,quote]
+\\markuplist {
+ \\override #'(padding . 2)
+ \\table
+ #'(0 1 0 -1)
+ {
+ \\underline { center-aligned right-aligned center-aligned left-aligned }
+ one \\number 1 thousandth \\number 0.001
+ eleven \\number 11 hundredth \\number 0.01
+ twenty \\number 20 tenth \\number 0.1
+ thousand \\number 1000 one \\number 1.0
+ }
+}
+@end lilypond
+"
+
+ (define (split-lst initial-lst lngth result-lst)
+ ;; split a list into a list of sublists of length lngth
+ ;; eg. (split-lst '(1 2 3 4 5 6) 2 '())
+ ;; -> ((1 2) (3 4) (5 6))
+ (cond ((not (integer? (/ (length initial-lst) lngth)))
+ (ly:warning
+ "Can't split list of length ~a into ~a parts, returning empty list"
+ (length initial-lst) lngth)
+ '())
+ ((null? initial-lst)
+ (reverse result-lst))
+ (else
+ (split-lst
+ (drop initial-lst lngth)
+ lngth
+ (cons (take initial-lst lngth) result-lst)))))
+
+ (define (dists-list init padding lst)
+ ;; Returns a list, where each element of `lst' is
+ ;; added to the sum of the previous elements of `lst' plus padding.
+ ;; `init' will be the first element of the resulting list. The addition
+ ;; starts with the values of `init', `padding' and `(car lst)'.
+ ;; eg. (dists-list 0.01 0.1 '(1 2 3 4)))
+ ;; -> (0.01 1.11 3.21 6.31 10.41)
+ (if (or (not (number? init))
+ (not (number? padding))
+ (not (number-list? lst)))
+ (begin
+ (ly:warning
+ "not fitting argument for `dists-list', return empty lst ")
+ '())
+ (reverse
+ (fold (lambda (elem rl) (cons (+ elem padding (car rl)) rl))
+ (list init)
+ lst))))
+
+ (let* (;; get the number of columns
+ (columns (length column-align))
+ (init-stils (interpret-markup-list layout props lst))
+ ;; If the given markup-list is the result of a markup-list call, their
+ ;; length may not be easily predictable, thus we add point-stencils
+ ;; to fill last row of the table.
+ (rem (remainder (length init-stils) columns))
+ (filled-stils
+ (if (zero? rem)
+ init-stils
+ (append init-stils (make-list (- columns rem) point-stencil))))
+ ;; get the stencils in sublists of length `columns'
+ (stils
+ (split-lst filled-stils columns '()))
+ ;; procedure to return stencil-length
+ ;; If it is nan, return 0
+ (lengths-proc
+ (lambda (m)
+ (let ((lngth (interval-length (ly:stencil-extent m X))))
+ (if (nan? lngth) 0 lngth))))
+ ;; get the max width of each column in a list
+ (columns-max-x-lengths
+ (map
+ (lambda (x)
+ (apply max 0
+ (map
+ lengths-proc
+ (map (lambda (l) (list-ref l x)) stils))))
+ (iota columns)))
+ ;; create a list of (basic) distances, which each column should
+ ;; moved, using `dists-list'. Some padding may be added.
+ (dist-sequence
+ (dists-list 0 padding columns-max-x-lengths))
+ ;; Get all stencils of a row, moved accurately to build columns.
+ ;; If the items of a column are aligned other than left, we need to
+ ;; move them to avoid collisions:
+ ;; center aligned: move all items half the width of the widest item
+ ;; right aligned: move all items the full width of the widest item.
+ ;; Added to the default-offset calculated in `dist-sequence'.
+ ;; `stencils-for-row-proc' needs four arguments:
+ ;; stil - a stencil
+ ;; dist - a numerical value as basic offset in X direction
+ ;; column - a numerical value for the column we're in
+ ;; x-align - a numerical value how current column should be
+ ;; aligned, where (-1, 0, 1) means (LEFT, CENTER, RIGHT)
+ (stencils-for-row-proc
+ (lambda (stil dist column x-align)
+ (ly:stencil-translate-axis
+ (ly:stencil-aligned-to stil X x-align)
+ (cond ((member x-align '(0 1))
+ (let* (;; get the stuff for relevant column
+ (stuff-for-column
+ (map
+ (lambda (s) (list-ref s column))
+ stils))
+ ;; get length of every column-item
+ (lengths-for-column
+ (map lengths-proc stuff-for-column))
+ (widest
+ (apply max 0 lengths-for-column)))
+ (+ dist (/ widest (if (= x-align 0) 2 1)))))
+ (else dist))
+ X)))
+ ;; get a list of rows using `ly:stencil-add' on a list of stencils
+ (rows
+ (map
+ (lambda (stil-list)
+ (apply ly:stencil-add
+ (map
+ ;; the procedure creating the stencils:
+ stencils-for-row-proc
+ ;; the procedure's args:
+ stil-list
+ dist-sequence
+ (iota columns)
+ column-align)))
+ stils)))
+ (space-lines baseline-skip rows)))
+
(define-markup-list-command (map-markup-commands layout props compose args)
(procedure? markup-list?)
"This applies the function @var{compose} to every markup in