]> git.donarmstrong.com Git - lilypond.git/blob - scm/define-markup-commands.scm
0b44e689a6912ad3057a4a64c51dc80046029255
[lilypond.git] / scm / define-markup-commands.scm
1 ;;;; define-markup-commands.scm -- markup commands
2 ;;;;
3 ;;;;  source file of the GNU LilyPond music typesetter
4 ;;;; 
5 ;;;; (c)  2000--2004  Han-Wen Nienhuys <hanwen@cs.uu.nl>
6 ;;;;                  Jan Nieuwenhuizen <janneke@gnu.org>
7
8 ;;; markup commands
9 ;;; TODO:
10 ;;;  * each markup function should have a doc string with
11 ;;     syntax, description and example. 
12
13 (define-public empty-stencil (ly:make-stencil '() '(1 . -1) '(1 . -1)))
14
15 (def-markup-command (stencil layout props stil) (ly:stencil?)
16   "Stencil as markup"
17   stil)
18
19
20 (def-markup-command (score layout props score) (ly:score?)
21   "Inline an image of music."
22   (let*
23       ((systems (ly:score-embedded-format score layout)))
24
25     (if (= 0 (vector-length systems))
26         (begin
27           (ly:warn "No systems found in \\score markup. Did you forget \\layout?")
28           empty-markup)
29         (begin
30           (let*
31               ((stencil (ly:paper-system-stencil  (vector-ref systems 0)))) 
32
33             (ly:stencil-align-to! stencil Y CENTER)
34             stencil)))))
35
36 (def-markup-command (simple layout props str) (string?)
37   "A simple text string; @code{\\markup @{ foo @}} is equivalent with
38 @code{\\markup @{ \\simple #\"foo\" @}}."
39     (interpret-markup layout props str))
40
41 (def-markup-command (encoded-simple layout props sym str) (symbol? string?)
42   "A text string, encoded with encoding @var{sym}. See
43 @usermanref{Text encoding} for more information."
44   (Text_interface::interpret_string layout
45                                props sym str))
46
47
48 ;; TODO: use font recoding.
49 ;;                    (make-line-markup
50 ;;                     (map make-word-markup (string-tokenize str)))))
51
52 (define-public empty-markup
53   (make-simple-markup ""))
54
55
56 (def-markup-command (postscript layout props str) (string?)
57
58   "This inserts @var{str} directly into the output as a PostScript
59 command string.  Due to technicalities of the output backends,
60 different scales should be used for the @TeX{} and PostScript backend,
61 selected with @code{-f}. 
62
63
64 For the TeX backend, the following string prints a rotated text
65
66 @cindex rotated text
67
68 @verbatim
69 0 0 moveto /ecrm10 findfont 
70 1.75 scalefont setfont 90 rotate (hello) show
71 @end verbatim
72
73 @noindent
74 The magical constant 1.75 scales from LilyPond units (staff spaces) to
75 TeX dimensions.
76
77 For the postscript backend, use the following
78
79 @verbatim
80 gsave /ecrm10 findfont 
81  10.0 output-scale div 
82  scalefont setfont  90 rotate (hello) show grestore 
83 @end verbatim
84 "
85   ;; FIXME
86   
87   (ly:make-stencil
88    (list 'embedded-ps str)
89    '(0 . 0) '(0 . 0)  ))
90
91 ;;(def-markup-command (fill-line layout props line-width markups)
92 ;;  (number? markup-list?)
93 ;; no parser tag -- should make number? markuk-list? thingy
94 (def-markup-command (fill-line layout props markups)
95   (markup-list?)
96   "Put @var{markups} in a horizontal line of width @var{line-width}.
97    The markups are spaced/flushed to fill the entire line.
98    If there are no arguments, return an empty stencil.
99 "
100
101   (let* ((stencils (filter
102                     (lambda (stc) (not (ly:stencil-empty? stc)))
103                     (map (lambda (x) (interpret-markup layout props x))
104                         markups)))
105          (text-width (apply + (map interval-length
106                                    (map (lambda (x)
107                                           (ly:stencil-extent x X))
108                                         stencils))))
109         (word-count (length stencils))
110         (word-space (chain-assoc-get 'word-space props))
111         (line-width (chain-assoc-get 'linewidth props))
112         (fill-space (if (< line-width text-width)
113                         word-space
114                         (/ (- line-width text-width)
115                            (if (= word-count 1) 2 (- word-count 1)))))
116         (line-stencils (if (= word-count 1)
117                            (list
118                             (ly:make-stencil '() '(0 . 0) '(0 . 0))  
119                             (car stencils)
120                             (ly:make-stencil '() '(0 . 0) '(0 . 0))  )
121                            stencils)))
122
123     (if (null? stencils)
124         empty-stencil
125         (stack-stencils X RIGHT fill-space line-stencils))))
126   
127 (define (font-markup qualifier value)
128   (lambda (layout props arg)
129     (interpret-markup layout
130                       (prepend-alist-chain qualifier value props)
131                       arg)))
132
133
134 (def-markup-command (line layout props args) (markup-list?)
135   "Put @var{args} in a horizontal line.  The property @code{word-space}
136 determines the space between each markup in @var{args}."
137   (stack-stencil-line
138    (chain-assoc-get 'word-space props)
139    (map (lambda (m) (interpret-markup layout props m)) args)))
140
141 (def-markup-command (fromproperty layout props symbol) (symbol?)
142   "Read the @var{symbol} from property settings, and produce a stencil from the markup contained within. If @var{symbol} is not defined, it returns an empty markup"
143   (let*
144       ((m (chain-assoc-get symbol props)))
145
146     (if (markup? m)
147         (interpret-markup layout props m)
148         (ly:make-stencil '()  '(1 . -1) '(1 . -1) ))))
149
150
151 (def-markup-command (on-the-fly layout props procedure arg) (symbol? markup?)
152   "Apply the @var{procedure} markup command to
153 @var{arg}. @var{procedure} should take a single argument."
154   (let*
155       ((anonymous-with-signature (lambda (layout props arg) (procedure layout props arg))))
156
157     (set-object-property! anonymous-with-signature
158                          'markup-signature
159                          (list markup?))
160     
161     (interpret-markup layout props (list anonymous-with-signature arg))
162   ))
163
164
165 (def-markup-command (combine layout props m1 m2) (markup? markup?)
166   "Print two markups on top of each other."
167   (let*
168       ((s1 (interpret-markup layout props m1))
169        (s2 (interpret-markup layout props m2)))
170              
171     (ly:stencil-add s1 s2)))
172
173 (def-markup-command (finger layout props arg) (markup?)
174   "Set the argument as small numbers."
175   (interpret-markup layout
176                     (cons '((font-size . -5) (font-encoding . fetaNumber)) props)
177                     arg))
178
179 (def-markup-command (fontsize layout props mag arg) (number? markup?)
180   "This sets the relative font size, e.g.
181 @example
182 A \\fontsize #2 @{ B C @} D
183 @end example
184
185
186 This will enlarge the B and the C by two steps.
187 "
188   (interpret-markup
189    layout 
190    (prepend-alist-chain 'font-size mag props)
191    arg))
192
193 (def-markup-command (magnify layout props sz arg) (number? markup?)
194   "This sets the font magnification for the its argument. In the following
195 example, the middle A will be 10% larger:
196 @example
197 A \\magnify #1.1 @{ A @} A
198 @end example
199
200 Note: magnification only works if a font-name is explicitly selected.
201 Use @code{\\fontsize} otherwise."
202
203   (interpret-markup
204    layout 
205    (prepend-alist-chain 'font-magnification sz props)
206    arg))
207
208 (def-markup-command (bold layout props arg) (markup?)
209   "Switch to bold font-series"
210   (interpret-markup layout (prepend-alist-chain 'font-series 'bold props) arg))
211
212 (def-markup-command (sans layout props arg) (markup?)
213   "Switch to the sans serif family"
214   (interpret-markup layout (prepend-alist-chain 'font-family 'sans props) arg))
215
216 (def-markup-command (number layout props arg) (markup?)
217   "Set font family to @code{number}, which yields the font used for
218 time signatures and fingerings.  This font only contains numbers and
219 some punctuation. It doesn't have any letters.  "
220   (interpret-markup layout (prepend-alist-chain 'font-encoding 'fetaNumber props) arg))
221
222 (def-markup-command (roman layout props arg) (markup?)
223   "Set font family to @code{roman}."
224   (interpret-markup layout (prepend-alist-chain 'font-family 'roman props) arg))
225
226 (def-markup-command (huge layout props arg) (markup?)
227   "Set font size to +2."
228   (interpret-markup layout (prepend-alist-chain 'font-size 2 props) arg))
229
230 (def-markup-command (large layout props arg) (markup?)
231   "Set font size to +1."
232   (interpret-markup layout (prepend-alist-chain 'font-size 1 props) arg))
233
234 (def-markup-command (normalsize layout props arg) (markup?)
235   "Set font size to default."
236   (interpret-markup layout (prepend-alist-chain 'font-size 0 props) arg))
237
238 (def-markup-command (small layout props arg) (markup?)
239   "Set font size to -1."
240   (interpret-markup layout (prepend-alist-chain 'font-size -1 props) arg))
241
242 (def-markup-command (tiny layout props arg) (markup?)
243   "Set font size to -2."
244   (interpret-markup layout (prepend-alist-chain 'font-size -2 props) arg))
245
246 (def-markup-command (teeny layout props arg) (markup?)
247   "Set font size to -3."
248   (interpret-markup layout (prepend-alist-chain 'font-size -3 props) arg))
249
250 (def-markup-command (caps layout props arg) (markup?)
251   "Set @code{font-shape} to @code{caps}."
252   (interpret-markup layout (prepend-alist-chain 'font-shape 'caps props) arg))
253
254 ;(def-markup-command (latin-i layout props arg) (markup?)
255 ;  "TEST latin1 encoding."
256 ;  (interpret-markup layout (prepend-alist-chain 'font-shape 'latin1 props) arg))
257
258 (def-markup-command (dynamic layout props arg) (markup?)
259   "Use the dynamic font.  This font only contains @b{s}, @b{f}, @b{m},
260 @b{z}, @b{p}, and @b{r}.  When producing phrases, like ``pi@`{u} @b{f}'', the
261 normal words (like ``pi@`{u}'') should be done in a different font.  The
262 recommend font for this is bold and italic"
263   (interpret-markup
264    layout (prepend-alist-chain 'font-encoding 'fetaDynamic props) arg))
265
266 (def-markup-command (italic layout props arg) (markup?)
267   "Use italic @code{font-shape} for @var{arg}. "
268   (interpret-markup layout (prepend-alist-chain 'font-shape 'italic props) arg))
269
270 (def-markup-command (typewriter layout props arg) (markup?)
271   "Use @code{font-family} typewriter for @var{arg}."
272   (interpret-markup
273    layout (prepend-alist-chain 'font-family 'typewriter props) arg))
274
275 (def-markup-command (upright layout props arg) (markup?)
276   "Set font shape to @code{upright}."
277   (interpret-markup
278    layout (prepend-alist-chain 'font-shape 'upright props) arg))
279
280 (def-markup-command (doublesharp layout props) ()
281   "Draw a double sharp symbol."
282
283   (interpret-markup layout props (markup #:musicglyph "accidentals-4")))
284 (def-markup-command (sesquisharp layout props) ()
285   "Draw a 3/2 sharp symbol."
286   (interpret-markup layout props (markup #:musicglyph "accidentals-3")))
287
288 (def-markup-command (sharp layout props) ()
289   "Draw a sharp symbol."
290   (interpret-markup layout props (markup #:musicglyph "accidentals-2")))
291 (def-markup-command (semisharp layout props) ()
292   "Draw a semi sharp symbol."
293   (interpret-markup layout props (markup #:musicglyph "accidentals-1")))
294 (def-markup-command (natural layout props) ()
295   "Draw a natural symbol."
296
297   (interpret-markup layout props (markup #:musicglyph "accidentals-0")))
298 (def-markup-command (semiflat layout props) ()
299   "Draw a semiflat."
300   (interpret-markup layout props (markup #:musicglyph "accidentals--1")))
301 (def-markup-command (flat layout props) ()
302   "Draw a flat symbol."
303   
304   (interpret-markup layout props (markup #:musicglyph "accidentals--2")))
305 (def-markup-command (sesquiflat layout props) ()
306   "Draw a 3/2 flat symbol."
307   
308   (interpret-markup layout props (markup #:musicglyph "accidentals--3")))
309 (def-markup-command (doubleflat layout props) ()
310   "Draw a double flat symbol."
311
312   (interpret-markup layout props (markup #:musicglyph "accidentals--4")))
313
314
315 (def-markup-command (column layout props args) (markup-list?)
316   "Stack the markups in @var{args} vertically."
317   (stack-lines
318    -1 0.0 (chain-assoc-get 'baseline-skip props)
319    (remove ly:stencil-empty?
320            (map (lambda (m) (interpret-markup layout props m)) args))))
321
322 (def-markup-command (dir-column layout props args) (markup-list?)
323   "Make a column of args, going up or down, depending on the setting
324 of the @code{#'direction} layout property."
325   (let* ((dir (chain-assoc-get 'direction props)))
326     (stack-lines
327      (if (number? dir) dir -1)
328      0.0
329       (chain-assoc-get 'baseline-skip props)
330      (map (lambda (x) (interpret-markup layout props x)) args))))
331
332 (def-markup-command (center-align layout props args) (markup-list?)
333   "Put @code{args} in a centered column. "
334   (let* ((mols (map (lambda (x) (interpret-markup layout props x)) args))
335          (cmols (map (lambda (x) (ly:stencil-align-to! x X CENTER)) mols)))
336     (stack-lines -1 0.0 (chain-assoc-get 'baseline-skip props) cmols)))
337
338 (def-markup-command (vcenter layout props arg) (markup?)
339   "Align @code{arg} to its center. "
340   (let* ((mol (interpret-markup layout props arg)))
341     (ly:stencil-align-to! mol Y CENTER)
342     mol))
343
344 (def-markup-command (right-align layout props arg) (markup?)
345   (let* ((m (interpret-markup layout props arg)))
346     (ly:stencil-align-to! m X RIGHT)
347     m))
348
349 (def-markup-command (left-align layout props arg) (markup?)
350   "Align @var{arg} on its left edge. "
351   
352   (let* ((m (interpret-markup layout props arg)))
353     (ly:stencil-align-to! m X LEFT)
354     m))
355
356 (def-markup-command (general-align layout props axis dir arg)  (integer? number? markup?)
357   "Align @var{arg} in @var{axis} direction to the @var{dir} side."
358   (let* ((m (interpret-markup layout props arg)))
359
360     (ly:stencil-align-to! m axis dir)
361     m
362   ))
363
364 (def-markup-command (halign layout props dir arg) (number? markup?)
365   "Set horizontal alignment. If @var{dir} is @code{-1}, then it is
366 left-aligned, while @code{+1} is right. Values in between interpolate
367 alignment accordingly."
368
369   
370   (let* ((m (interpret-markup layout props arg)))
371     (ly:stencil-align-to! m X dir)
372     m))
373
374 (def-markup-command (musicglyph layout props glyph-name) (string?)
375   "This is converted to a musical symbol, e.g. @code{\\musicglyph
376 #\"accidentals-0\"} will select the natural sign from the music font.
377 See @usermanref{The Feta font} for  a complete listing of the possible glyphs.
378 "
379   (ly:find-glyph-by-name
380    (ly:paper-get-font layout (cons '((font-encoding . fetaMusic))
381                                   props))
382    glyph-name))
383
384
385 (def-markup-command (lookup layout props glyph-name) (string?)
386   "Lookup a glyph by name."
387   (ly:find-glyph-by-name (ly:paper-get-font layout props)
388                          glyph-name))
389
390 (def-markup-command (char layout props num) (integer?)
391   "Produce a single character, e.g. @code{\\char #65} produces the 
392 letter 'A'."
393   (ly:get-glyph (ly:paper-get-font layout props) num))
394
395 (def-markup-command (raise layout props amount arg) (number? markup?)
396   "
397 This  raises  @var{arg}, by the distance @var{amount}.
398 A negative @var{amount} indicates lowering:
399 @c
400 @lilypond[verbatim,fragment,relative=1]
401  c1^\\markup { C \\small \\raise #1.0 \\bold { \"9/7+\" }}
402 @end lilypond
403 The argument to @code{\\raise} is the vertical displacement amount,
404 measured in (global) staff spaces.  @code{\\raise} and @code{\\super}
405 raise objects in relation to their surrounding markups.
406
407 If the text object itself is positioned above or below the staff, then
408 @code{\\raise} cannot be used to move it, since the mechanism that
409 positions it next to the staff cancels any shift made with
410 @code{\\raise}. For vertical positioning, use the @code{padding}
411 and/or @code{extra-offset} properties. "
412
413   
414   (ly:stencil-translate-axis (interpret-markup layout props arg)
415                               amount Y))
416
417 (def-markup-command (fraction layout props arg1 arg2) (markup? markup?)
418   "Make a fraction of two markups."
419   
420   (let* ((m1 (interpret-markup layout props arg1))
421          (m2 (interpret-markup layout props arg2)))
422     (ly:stencil-align-to! m1 X CENTER)
423     (ly:stencil-align-to! m2 X CENTER)    
424     (let* ((x1 (ly:stencil-extent m1 X))
425            (x2 (ly:stencil-extent m2 X))
426            (line (ly:round-filled-box (interval-union x1 x2) '(-0.05 . 0.05) 0.0))
427            ;; should stack mols separately, to maintain LINE on baseline
428            (stack (stack-lines -1 0.2 0.6 (list m1 line m2))))
429       (ly:stencil-align-to! stack Y CENTER)
430       (ly:stencil-align-to! stack X LEFT)
431       ;; should have EX dimension
432       ;; empirical anyway
433       (ly:stencil-translate-axis stack 0.75 Y))))
434
435
436 ;; TODO: better syntax.
437
438 (def-markup-command (note-by-number layout props log dot-count dir) (number? number? number?)
439   "Construct a note symbol, with stem.  By using fractional values for
440 @var{dir}, you can obtain longer or shorter stems."
441   
442   (let* ((font (ly:paper-get-font layout (cons '((font-encoding . fetaMusic)) props)))
443          (size (chain-assoc-get 'font-size props 0))
444          (stem-length (* (magstep size) (max 3 (- log 1))))
445          (head-glyph (ly:find-glyph-by-name
446                   font
447                   (string-append "noteheads-" (number->string (min log 2)))))
448          (stem-thickness 0.13)
449          (stemy (* dir stem-length))
450          (attachx (if (> dir 0)
451                       (- (cdr (ly:stencil-extent head-glyph X)) stem-thickness)
452                       0))
453          (attachy (* dir 0.28))
454          (stem-glyph (and (> log 0)
455                       (ly:round-filled-box
456                        (cons attachx (+ attachx  stem-thickness))
457                        (cons (min stemy attachy)
458                              (max stemy attachy))
459                        (/ stem-thickness 3))))
460          (dot (ly:find-glyph-by-name font "dots-dot"))
461          (dotwid (interval-length (ly:stencil-extent dot X)))
462          (dots (and (> dot-count 0)
463                     (apply ly:stencil-add
464                            (map (lambda (x)
465                                   (ly:stencil-translate-axis
466                                    dot  (* (+ 1 (* 2 x)) dotwid) X) )
467                                 (iota dot-count 1)))))
468          (flaggl (and (> log 2)
469                       (ly:stencil-translate
470                        (ly:find-glyph-by-name font
471                                               (string-append "flags-"
472                                                              (if (> dir 0) "u" "d")
473                                                              (number->string log)))
474                        (cons (+ attachx (/ stem-thickness 2)) stemy)))))
475     (if flaggl
476         (set! stem-glyph (ly:stencil-add flaggl stem-glyph)))
477     (if (ly:stencil? stem-glyph)
478         (set! stem-glyph (ly:stencil-add stem-glyph head-glyph))
479         (set! stem-glyph head-glyph))
480     (if (ly:stencil? dots)
481         (set! stem-glyph
482               (ly:stencil-add
483                (ly:stencil-translate-axis dots
484                                            (+ (if (and (> dir 0) (> log 2))
485                                                   (* 1.5 dotwid)
486                                                   0)
487                                               ;; huh ? why not necessary?
488                                               ;;(cdr (ly:stencil-extent head-glyph X))
489                                               dotwid)
490                                            X)
491                stem-glyph)))
492     stem-glyph))
493
494 (use-modules (ice-9 regex))
495
496 (define-public log2 
497   (let ((divisor (log 2)))
498     (lambda (z) (inexact->exact (/ (log z) divisor)))))
499
500 (define (parse-simple-duration duration-string)
501   "Parse the `duration-string', e.g. ''4..'' or ''breve.'', and return a (log dots) list."
502   (let ((match (regexp-exec (make-regexp "(breve|longa|maxima|[0-9]+)(\\.*)") duration-string)))
503     (if (and match (string=? duration-string (match:substring match 0)))
504         (let ((len  (match:substring match 1))
505               (dots (match:substring match 2)))
506           (list (cond ((string=? len "breve")  -1)
507                       ((string=? len "longa")  -2)
508                       ((string=? len "maxima") -3)
509                       (else (log2 (string->number len))))
510                 (if dots (string-length dots) 0)))
511         (error "This is not a valid duration string:" duration-string))))
512
513 (def-markup-command (note layout props duration dir) (string? number?)
514   "This produces a note with a stem pointing in @var{dir} direction, with
515 the @var{duration} for the note head type and augmentation dots. For
516 example, @code{\\note #\"4.\" #-0.75} creates a dotted quarter note, with
517 a shortened down stem."
518   
519   (let ((parsed (parse-simple-duration duration)))
520     (note-by-number-markup layout props (car parsed) (cadr parsed) dir)))
521
522 (def-markup-command (normal-size-super layout props arg) (markup?)
523   "Set @var{arg} in superscript with a normal font size."
524   
525   (ly:stencil-translate-axis (interpret-markup
526                                layout
527                                props arg)
528                               (* 0.5  (chain-assoc-get 'baseline-skip props))
529                               Y))
530
531 (def-markup-command (super layout props arg) (markup?)
532   "
533 @cindex raising text
534 @cindex lowering text
535 @cindex moving text
536 @cindex translating text
537
538 @cindex @code{\\super}
539
540
541 Raising and lowering texts can be done with @code{\\super} and
542 @code{\\sub}:
543
544 @lilypond[verbatim,fragment,relative=1]
545  c1^\\markup { E \"=\" mc \\super \"2\" }
546 @end lilypond
547
548 "
549   
550   (ly:stencil-translate-axis
551    (interpret-markup
552     layout
553     (cons `((font-size . ,(- (chain-assoc-get 'font-size props 0) 3))) props)
554     arg)
555    (* 0.5 (chain-assoc-get 'baseline-skip props))
556    Y))
557
558 (def-markup-command (translate layout props offset arg) (number-pair? markup?)
559   "This translates an object. Its first argument is a cons of numbers
560 @example
561 A \\translate #(cons 2 -3) @{ B C @} D
562 @end example
563 This moves `B C' 2 spaces to the right, and 3 down, relative to its
564 surroundings. This command cannot be used to move isolated scripts
565 vertically, for the same reason that @code{\\raise} cannot be used for
566 that.
567
568 "
569   
570   (ly:stencil-translate (interpret-markup  layout props arg)
571                          offset))
572
573 (def-markup-command (sub layout props arg) (markup?)
574   "Set @var{arg} in subscript."
575   
576   (ly:stencil-translate-axis
577    (interpret-markup
578     layout
579     (cons `((font-size . ,(- (chain-assoc-get 'font-size props 0) 3))) props)
580     arg)
581    (* -0.5 (chain-assoc-get 'baseline-skip props))
582    Y))
583
584 (def-markup-command (normal-size-sub layout props arg) (markup?)
585   "Set @var{arg} in subscript, in a normal font size."
586
587   (ly:stencil-translate-axis
588    (interpret-markup layout props arg)
589    (* -0.5 (chain-assoc-get 'baseline-skip props))
590    Y))
591
592 (def-markup-command (hbracket layout props arg) (markup?)
593   "Draw horizontal brackets around @var{arg}."  
594   (let ((th 0.1) ;; todo: take from GROB.
595         (m (interpret-markup layout props arg)))
596     (bracketify-stencil m X th (* 2.5 th) th)))
597
598 (def-markup-command (bracket layout props arg) (markup?)
599   "Draw vertical brackets around @var{arg}."  
600   (let ((th 0.1) ;; todo: take from GROB.
601         (m (interpret-markup layout props arg)))
602     (bracketify-stencil m Y th (* 2.5 th) th)))
603
604 ;; todo: fix negative space
605 (def-markup-command (hspace layout props amount) (number?)
606   "This produces a invisible object taking horizontal space.
607 @example 
608 \\markup @{ A \\hspace #2.0 B @} 
609 @end example
610 will put extra space between A and B, on top of the space that is
611 normally inserted before elements on a line.
612 "
613   (if (> amount 0)
614       (ly:make-stencil "" (cons 0 amount) '(-1 . 1) )
615       (ly:make-stencil "" (cons amount amount) '(-1 . 1))))
616
617 (def-markup-command (override layout props new-prop arg) (pair? markup?)
618   "Add the first argument in to the property list.  Properties may be
619 any sort of property supported by @internalsref{font-interface} and
620 @internalsref{text-interface}, for example
621
622 @verbatim
623 \\override #'(font-family . married) \"bla\"
624 @end verbatim
625
626 "
627   (interpret-markup layout (cons (list new-prop) props) arg))
628
629 (def-markup-command (smaller layout props arg) (markup?)
630   "Decrease the font size relative to current setting"
631   (let* ((fs (chain-assoc-get 'font-size props 0))
632          (entry (cons 'font-size (- fs 1))))
633     (interpret-markup layout (cons (list entry) props) arg)))
634
635
636 (def-markup-command (bigger layout props arg) (markup?)
637   "Increase the font size relative to current setting"
638   (let* ((fs (chain-assoc-get 'font-size props 0))
639          (entry (cons 'font-size (+ fs 1))))
640     (interpret-markup layout (cons (list entry) props) arg)))
641
642 (def-markup-command larger (markup?)
643   bigger-markup)
644
645
646 (def-markup-command (box layout props arg) (markup?)
647   "Draw a box round @var{arg}.  Looks at @code{thickness} and
648 @code{box-padding} properties to determine line thickness and padding
649 around the markup."
650   (let ((th (chain-assoc-get 'thickness props  0.1))
651         (pad (chain-assoc-get 'box-padding props 0.2))
652         (m (interpret-markup layout props arg)))
653     (box-stencil m th pad)))
654
655 ;FIXME: is this working? 
656 (def-markup-command (strut layout props) ()
657   
658   "Create a box of the same height as the space in the current font."
659   
660   (let ((m (Text_interface::interpret_markup layout props " ")))
661     (ly:stencil-set-extent! m X '(1000 . -1000))
662     m))
663
664 (define number->mark-letter-vector (make-vector 25 #\A))
665
666 (do ((i 0 (1+ i))
667      (j 0 (1+ j)))
668     ((>= i 26))
669   (if (= i (- (char->integer #\I) (char->integer #\A)))
670       (set! i (1+ i)))
671   (vector-set! number->mark-letter-vector j
672                (integer->char (+ i (char->integer #\A)))))
673
674 (define (number->markletter-string n)
675   "Double letters for big marks."
676   (let*
677       ((l (vector-length number->mark-letter-vector)))
678     
679   (if (>= n l)
680       (string-append (number->markletter-string (1- (quotient n l)))
681                      (number->markletter-string (remainder n l)))
682       (make-string 1 (vector-ref number->mark-letter-vector n)))))
683
684
685 (def-markup-command (markletter layout props num) (integer?)
686    "Make a markup letter for @var{num}.  The letters start with A to Z
687  (skipping I), and continues with double letters."
688  
689    (Text_interface::interpret_markup layout props (number->markletter-string num)))
690
691
692
693
694 (def-markup-command (bracketed-y-column layout props indices args)
695   (list? markup-list?)
696   "Make a column of the markups in @var{args}, putting brackets around
697 the elements marked in @var{indices}, which is a list of numbers."
698
699     (define (sublist l start stop)
700     (take (drop l start)  (- (1+ stop) start)) )
701
702   (define (stencil-list-extent ss axis)
703     (cons
704      (apply min (map (lambda (x) (car (ly:stencil-extent x axis))) ss))
705      (apply max (map (lambda (x) (cdr (ly:stencil-extent x axis))) ss))))
706             
707   (define (stack-stencils stencils bskip last-stencil)
708     (cond
709      ((null? stencils) '())
710      ((not last-stencil)
711       (cons (car stencils)
712             (stack-stencils (cdr stencils) bskip (car stencils))))
713      (else
714       (let*
715           ((orig (car stencils))
716            (dir (chain-assoc-get 'direction  props DOWN))
717            (new (ly:stencil-moved-to-edge last-stencil Y dir
718                                           orig
719                                           0.1 bskip))
720            )
721
722         (cons new (stack-stencils (cdr stencils) bskip new))))
723     ))
724
725   (define (make-brackets stencils indices acc)
726     (if (and stencils
727              (pair? indices)
728              (pair? (cdr indices)))
729         (let*
730             ((encl (sublist stencils (car indices) (cadr indices)))
731              (x-ext (stencil-list-extent encl X))
732              (y-ext (stencil-list-extent encl Y))
733              (thick 0.10)
734              (pad 0.35)
735              (protusion (* 2.5 thick))
736              (lb
737               (ly:stencil-translate-axis 
738                (ly:bracket Y y-ext thick protusion)
739                (- (car x-ext) pad) X))
740              (rb (ly:stencil-translate-axis
741                   (ly:bracket Y y-ext thick (- protusion))
742                   (+ (cdr x-ext) pad) X))
743              )
744
745           (make-brackets
746            stencils (cddr indices)
747            (append
748             (list lb rb)
749              acc)))
750         acc))
751
752   (let*
753       ((stencils
754         (map (lambda (x)
755                (interpret-markup
756                 layout
757                 props
758                 x)) args))
759        (leading
760          (chain-assoc-get 'baseline-skip props))
761        (stacked (stack-stencils stencils 1.25 #f))
762        (brackets (make-brackets stacked indices '()))
763        )
764
765     (apply ly:stencil-add
766            (append stacked brackets)
767            )))
768
769
770              
771
772   
773   
774
775