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