1 %------------------------------------------------------------------%
2 % Opéra Libre -- text-functions.ly %
4 % (c) Valentin Villenave, 2008 %
6 %------------------------------------------------------------------%
8 #(use-modules
(ice-
9 regex
))
9 #(use-modules
(ice-
9 optargs
))
11 %%%%%%%%%%%%%%%%%%%%%%%%%%% Definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 %% Advanced definitions -------------------------------------------%
15 %%% This code was provided by Nicolas Sceaux.
17 #(define-public string-upper-case
#f)
18 #(define accented-char-upper-case?
#f)
19 #(define accented-char-lower-case?
#f)
21 %%;; an accented character is seen as two characters by guile
22 #(let
((lower-case-accented-string
"éèêëáàâäíìîïóòôöúùûüçœæ")
23 (upper-case-accented-string
"ÉÈÊËÁÀÂÄÍÌÎÏÓÒÔÖÚÙÛÜÇŒÆ"))
24 (define
(group-by-
2 chars result
)
25 (if
(or
(null? chars
) (null?
(cdr chars
)))
27 (group-by-
2 (cddr chars
)
28 (cons
(string
(car chars
) (cadr chars
))
30 (let
((lower-case-accented-chars
31 (group-by-
2 (string-
>list lower-case-accented-string
) (list
)))
32 (upper-case-accented-chars
33 (group-by-
2 (string-
>list upper-case-accented-string
) (list
))))
34 (set
! string-upper-case
36 (define
(replace-chars str froms tos
)
39 (replace-chars
(regexp-substitute
/global
#f (car froms
) str
43 (string-upcase
(replace-chars str
44 lower-case-accented-chars
45 upper-case-accented-chars
))))
46 (set
! accented-char-upper-case?
48 (member
(string char
1 char
2) upper-case-accented-chars string
=?
)))
49 (set
! accented-char-lower-case?
51 (member
(string char
1 char
2) lower-case-accented-chars string
=?
)))))
53 #(define-markup-command
(smallCaps layout props text
) (markup?
)
54 "Turn @code{text}, which should be a string, to small caps.
56 \\markup \\small-caps \"Text between double quotes\"
58 (define
(string-list-
>markup strings lower
)
59 (let
((final-string
(string-upper-case
60 (apply string-append
(reverse strings
)))))
62 (markup
#:fontsize -
2 final-string
)
64 (define
(make-small-caps rest-chars currents current-is-lower prev-result
)
65 (if
(null? rest-chars
)
66 (make-concat-markup
(reverse
! (cons
(string-list-
>markup
67 currents current-is-lower
)
69 (let
* ((ch
1 (car rest-chars
))
70 (ch
2 (and
(not
(null?
(cdr rest-chars
))) (cadr rest-chars
)))
71 (this-char-string
(string ch
1))
72 (is-lower
(char-lower-case? ch
1))
73 (next-rest-chars
(cdr rest-chars
)))
74 (cond
((and ch
2 (accented-char-lower-case? ch
1 ch
2))
75 (set
! this-char-string
(string ch
1 ch
2))
77 (set
! next-rest-chars
(cddr rest-chars
)))
78 ((and ch
2 (accented-char-upper-case? ch
1 ch
2))
79 (set
! this-char-string
(string ch
1 ch
2))
81 (set
! next-rest-chars
(cddr rest-chars
))))
82 (if
(or
(and current-is-lower is-lower
)
83 (and
(not current-is-lower
) (not is-lower
)))
84 (make-small-caps next-rest-chars
85 (cons this-char-string currents
)
88 (make-small-caps next-rest-chars
89 (list this-char-string
)
93 (cons
(string-list-
>markup
94 currents current-is-lower
)
96 (interpret-markup layout props
98 (make-small-caps
(string-
>list text
) (list
) #f (list
))
101 %% Graphic fine-tuning --------------------------------------------%
103 #(define-markup-command
(vspace layout props amount
) (number?
)
104 (let
((amount
(* amount
3.0)))
106 (ly
:make-stencil
"" (cons -
1 1) (cons
0 amount
))
107 (ly
:make-stencil
"" (cons -
1 1) (cons amount amount
)))))
109 #(define-public
(rounded-whiteout-stencil stencil blot
)
111 ((x-ext
(ly
:stencil-extent stencil X
))
112 (y-ext
(ly
:stencil-extent stencil Y
)))
114 (stencil-with-color
(ly
:round-filled-box x-ext y-ext blot
)
118 %TODO: make radius arg optional.
119 #(define-markup-command
(rounded-whiteout layout props radius arg
)
121 (rounded-whiteout-stencil
(interpret-markup layout props arg
) radius
))
123 #(define-markup-command
(line-width-ratio layout props width-ratio arg
) (number? markup?
)
124 (interpret-markup layout props
125 (markup
#:override
(cons
'line-width
(* width-ratio
(chain-assoc-get
'line-width props
)))
128 %% Expressive indications -----------------------------------------%
130 #(define-markup-command
(indic layout props arg
) (markup?
)
131 (interpret-markup layout props
132 (markup
#:rounded-whiteout
1 #:small
#:italic arg
)))
134 %% Dynamics -------------------------------------------------------%
136 %%% This function was provided by Graham Percival.
137 #(define
(make-dynamic-extra dynamic string
)
139 'AbsoluteDynamicEvent
141 ;; calculate centering for text
142 (list
(cons
(quote X-offset
)
143 (+ -
0.5 (* -
0.5 (string-length dynamic
)))))
145 (markup
#:rounded-whiteout
1
149 #:normal-text
#:italic string
))
152 #(define
(make-extra-dynamic string dynamic
)
154 'AbsoluteDynamicEvent
156 ;; calculate centering for text
157 (list
(cons
(quote X-offset
)
158 (+ -
0.5 (* -
0.5 (string-length dynamic
)))))
160 (markup
#:rounded-whiteout
1
162 #:normal-text
#:italic string
167 %%%%%%%%%%%%%%%%%%%%%%%%%% In-score Text %%%%%%%%%%%%%%%%%%%%%%%%%%%
170 %% Non-standard synamics ------------------------------------------%
172 fpp
= #(make-dynamic-script
"fpp")
173 sffz
= #(make-dynamic-script
"sffz")
176 %% Composite Dynamics ---------------------------------------------%
178 % because of the use of a music-function,
179 % non-predefined composite dynamics have to be entered *before*
180 % the affected beat (unlike standard or predefined dynamics).
182 #(define-music-function
(parser location dyn str
) (string? string?
)
183 (make-music
'SequentialMusic
'elements
185 (make-music
'OverrideProperty
187 'grob-property-path
(list
'self-alignment-X
)
188 'grob-value -
0.6 'once
#t
)
189 (make-music
'AbsoluteDynamicEvent
191 (markup
#:rounded-whiteout
1
192 #:line
(#:dynamic dyn
194 #:text
#:medium
#:italic str
))))))
197 #(define-music-function
(parser location str dyn
) (string? string?
)
198 (make-music
'SequentialMusic
'elements
200 (make-music
'OverrideProperty
202 'grob-property-path
(list
'self-alignment-X
)
203 'grob-value -
0.6 'once
#t
)
204 (make-music
'AbsoluteDynamicEvent
206 (markup
#:rounded-whiteout
1
207 #:line
(#:text
#:medium
#:italic str
211 %% Predefined commands
213 ffsubito
= #(make-dynamic-extra
"ff" "subito")
214 fsubito
= #(make-dynamic-extra
"f" "subito")
215 fsempre
= #(make-dynamic-extra
"f" "sempre")
216 mfsubito
= #(make-dynamic-extra
"mf" "subito")
217 fmolto
= #(make-dynamic-extra
"f" "molto")
218 psempre
= #(make-dynamic-extra
"p" "sempre")
219 ppsempre
= #(make-dynamic-extra
"pp" "sempre")
220 mfsempre
= #(make-dynamic-extra
"mf" "sempre")
221 mfintenso
= #(make-dynamic-extra
"mf" "intenso")
222 mpsostenuto
= #(make-dynamic-extra
"mp" "sostenuto")
223 psubito
= #(make-dynamic-extra
"p" "subito")
224 pdolce
= #(make-dynamic-extra
"p" "dolce")
225 pleggiero
= #(make-dynamic-extra
"p" "leggiero")
226 ppsubito
= #(make-dynamic-extra
"pp" "subito")
227 mfleggiero
= #(make-dynamic-extra
"mf" "leggiero")
228 piuf
= #(make-extra-dynamic
"più" "f")
229 pocof
= #(make-extra-dynamic
"poco" "f")
232 %% Text indications -----------------------------------------------%
235 #(define-music-function
(parser location text music
) (string? ly
:music?
)
237 (equal?
(ly
:music-property music
'name
) 'EventChord
)
238 (set
! (ly
:music-property music
'elements
)
239 (append
(ly
:music-property music
'elements
)
240 (list
(make-music
'TextScriptEvent
'direction
1
241 'text
(markup
#:indic text
))))))
245 #(define-music-function
(parser location texte
)
248 (markup
#:text
#:indic texte
)))
250 %% Predefined commands
253 #(define-music-function
(parser location music
) (ly
:music?
)
255 (equal?
(ly
:music-property music
'name
) 'EventChord
)
256 (set
! (ly
:music-property music
'elements
)
257 (append
(ly
:music-property music
'elements
)
258 (list
(make-music
'TextScriptEvent
'text
259 (markup
#:translate
(cons
4 0)
260 #:indic
"(ten.)"))))))
265 #(define-music-function
(parser location music
) (ly
:music?
)
266 #{ \ind #"pizz." $music
#})
269 #(define-music-function
(parser location music
) (ly
:music?
)
270 #{ \ind #"arco" $music
#})
273 #(define-music-function
(parser location music
) (ly
:music?
)
274 #{ \ind #"flautando" $music
#})
277 #(define-music-function
(parser location music
) (ly
:music?
)
278 #{ \ind #"simile" $music
#})
281 #(define-music-function
(parser location music
) (ly
:music?
)
282 #{ \ind #"loco" $music
#})
285 #(define-music-function
(parser location music
) (ly
:music?
)
286 #{ \ind #"(ordin.)" $music
#})
289 #(define-music-function
(parser location music
) (ly
:music?
)
290 #{ \ind #"meno" $music
#})
293 #(define-music-function
(parser location music
) (ly
:music?
)
294 #{ \ind #"jeté" $music
#})
297 %% Text Spanners --------------------------------------------------%
299 #(define
(make-txt-span music t
)
300 (set
! (ly
:music-property music
'elements
)
301 (append
(ly
:music-property music
'elements
)
302 (list
(make-music
'TextSpanEvent
303 'span-direction t
))))
306 %% The two following functions are deprecated. Better code follows below.
308 #(define-music-function
(parser location texte music
) (string? ly
:music?
)
309 #{ \override TextSpanner
#'bound-details
#'left
#'text
=
310 \markup { \bold $texte
}
311 $
(make-txt-span music -
1)#})
314 #(define-music-function
(parser location music
) (ly
:music?
)
315 (make-txt-span music
1))
317 #(define
(make-text-span txt
)
318 "Make a TextSpanner that begins with the given STR."
319 (let
* ((m
(make-music
'TextSpanEvent
321 (details
(assoc-get
'bound-details
322 (assoc-get
'TextSpanner
323 all-grob-descriptions
)))
324 (left-details
(assoc-get
'left
326 (ly
:music-set-property
! m
'tweaks
327 (acons
'bound-details
332 (ly
:music-property m
'tweaks
)))
336 #(define-music-function
(location parser txt
) (string?
)
337 (make-text-span txt
))
339 stopText
= #(make-music
'TextSpanEvent
'span-direction
1)
341 %% Predefined commands
343 rit
= #(make-text-span
"rit.")
347 %%%%%%%%%%%%%%%%%%%%%%%%%%%% Other Text %%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %% Lyrics formatting ----------------------------------------------%
353 \override Lyrics
. LyricExtender
#'stencil
= ##f }
356 \revert Lyrics
. LyricExtender
#'stencil
}
359 \once \override LyricText
#'self-alignment-X
= #0.9 }
362 \once \override LyricHyphen
#'minimum-distance
= #4
363 \once \override LyricHyphen
#'length
= #2
364 \once \override LyricHyphen
#'thickness
= #1.2
368 \once \override LyricText
#'font-shape
= #'italic
}
371 \override LyricText
#'font-shape
= #'caps
}
374 \revert LyricText
#'font-shape
}
377 %% Scenography formatting ---------------------------------------%
379 \once \override TextScript
#'extra-spacing-width
= #'(0 . 0)
380 \once \override TextScript
#'infinite-spacing-height
= ##t
383 #(define-markup-command
(did layout props text
) (markup?
)
384 (interpret-markup layout props
385 (markup
#:override
'(line-width
. 40)
386 #:override
'(box-padding
. 1)
387 #:override
'(corner-radius
. 2)
388 #:rounded-box
#:sans
#:italic
#:small
#:justify-string text
)))
390 #(define-markup-command
(init-did layout props text
) (markup?
)
391 (interpret-markup layout props
393 ;
#:override
(cons
'line-width
(* 1 (chain-assoc-get
'line-width props
)))
395 #:override
'(line-width
. 60)
396 #:override
'(box-padding
. 1.5)
397 #:override
'(corner-radius
. 2)
398 #:rounded-box
#:sans
#:italic
#:small
#:justify-string text
))))
401 %% Table of contents --------------------------------------------%
403 #(define-music-function
(parser location text
) (markup?
)
404 (add-toc-item
! 'tocActMarkup text
))
407 #(define-music-function
(parser location text
) (markup?
)
408 (add-toc-item
! 'tocQuoteMarkup text
))
410 %% Characters and instrument names ------------------------------%
412 #(define characters `
((dummy
. "")))
413 #(define instruments `
((dummy
. "")))
415 #(define
(char-name n
) (car
(car
(assoc-get n characters
))))
416 #(define
(char-shortname n
) (cdr
(car
(assoc-get n characters
))))
417 #(define
(instr-name n
) (car
(car
(assoc-get n instruments
))))
418 #(define
(instr-shortname n
) (cdr
(car
(assoc-get n instruments
))))
420 #(define
(make-char-name n
. pad
)
421 (let
* ((txt
(char-name n
))
422 (srt
(char-shortname n
))
424 (markup
#:hcenter-in
(car pad
) txt
)
426 (n
(markup srt
))) fixme
: shortname has no padding
427 (ly
:export
(make-sequential-music
(list
428 (context-spec-music
(make-property-set
'instrumentName m
)
430 (context-spec-music
(make-property-set
'shortInstrumentName n
)
432 (context-spec-music
(make-property-set
'midiInstrument
"voice oohs")
435 #(define
(make-instrument-name n midi
. pad
)
436 (let
* ((txt
(instr-name n
))
437 (srt
(instr-shortname n
))
439 (markup
#:hcenter-in
(car pad
) txt
)
441 (n
(markup srt
))) ;; fixme
: shortname has no padding
442 (ly
:export
(make-sequential-music
(list
443 (context-spec-music
(make-property-set
'instrumentName m
)
445 (context-spec-music
(make-property-set
'shortInstrumentName n
)
447 (context-spec-music
(make-property-set
'midiInstrument midi
)