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 mpsempre
= #(make-dynamic-extra
"mp" "sempre")
221 mfsempre
= #(make-dynamic-extra
"mf" "sempre")
222 mfintenso
= #(make-dynamic-extra
"mf" "intenso")
223 mpsostenuto
= #(make-dynamic-extra
"mp" "sostenuto")
224 psubito
= #(make-dynamic-extra
"p" "subito")
225 pdolce
= #(make-dynamic-extra
"p" "dolce")
226 ppdolce
= #(make-dynamic-extra
"pp" "dolce")
227 pleggiero
= #(make-dynamic-extra
"p" "leggiero")
228 ppleggiero
= #(make-dynamic-extra
"pp" "leggiero")
229 ppsubito
= #(make-dynamic-extra
"pp" "subito")
230 mfleggiero
= #(make-dynamic-extra
"mf" "leggiero")
231 piuf
= #(make-extra-dynamic
"più" "f")
232 pocof
= #(make-extra-dynamic
"poco" "f")
235 %% Text indications -----------------------------------------------%
238 #(define-music-function
(parser location text music
) (string? ly
:music?
)
240 (equal?
(ly
:music-property music
'name
) 'EventChord
)
241 (set
! (ly
:music-property music
'elements
)
242 (append
(ly
:music-property music
'elements
)
243 (list
(make-music
'TextScriptEvent
'direction
1
244 'text
(markup
#:indic text
))))))
248 #(define-music-function
(parser location texte
)
251 (markup
#:text
#:indic texte
)))
253 %% Predefined commands
256 #(define-music-function
(parser location music
) (ly
:music?
)
258 (equal?
(ly
:music-property music
'name
) 'EventChord
)
259 (set
! (ly
:music-property music
'elements
)
260 (append
(ly
:music-property music
'elements
)
261 (list
(make-music
'TextScriptEvent
'text
262 (markup
#:translate
(cons
4 0)
263 #:indic
"(ten.)"))))))
268 #(define-music-function
(parser location music
) (ly
:music?
)
269 #{ \ind #"pizz." $music
#})
272 #(define-music-function
(parser location music
) (ly
:music?
)
273 #{ \ind #"arco" $music
#})
276 #(define-music-function
(parser location music
) (ly
:music?
)
277 #{ \ind #"flautando" $music
#})
280 #(define-music-function
(parser location music
) (ly
:music?
)
281 #{ \ind #"simile" $music
#})
284 #(define-music-function
(parser location music
) (ly
:music?
)
285 #{ \ind #"loco" $music
#})
288 #(define-music-function
(parser location music
) (ly
:music?
)
289 #{ \ind #"(ordin.)" $music
#})
292 #(define-music-function
(parser location music
) (ly
:music?
)
293 #{ \ind #"meno" $music
#})
296 #(define-music-function
(parser location music
) (ly
:music?
)
297 #{ \ind #"jeté" $music
#})
300 %% Text Spanners --------------------------------------------------%
302 #(define
(make-txt-span music t
)
303 (set
! (ly
:music-property music
'elements
)
304 (append
(ly
:music-property music
'elements
)
305 (list
(make-music
'TextSpanEvent
306 'span-direction t
))))
309 %% The two following functions are deprecated. Better code follows below.
311 #(define-music-function
(parser location texte music
) (string? ly
:music?
)
312 #{ \override TextSpanner
#'bound-details
#'left
#'text
=
313 \markup { \bold $texte
}
314 $
(make-txt-span music -
1)#})
317 #(define-music-function
(parser location music
) (ly
:music?
)
318 (make-txt-span music
1))
320 #(define
(make-text-span txt
)
321 "Make a TextSpanner that begins with the given STR."
322 (let
* ((m
(make-music
'TextSpanEvent
324 (details
(assoc-get
'bound-details
325 (assoc-get
'TextSpanner
326 all-grob-descriptions
)))
327 (left-details
(assoc-get
'left
329 (ly
:music-set-property
! m
'tweaks
330 (acons
'bound-details
335 (ly
:music-property m
'tweaks
)))
339 #(define-music-function
(location parser txt
) (string?
)
340 (make-text-span txt
))
342 stopText
= #(make-music
'TextSpanEvent
'span-direction
1)
344 %% Predefined commands
346 rit
= #(make-text-span
"rit.")
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%% Other Text %%%%%%%%%%%%%%%%%%%%%%%%%%%%
353 %% Lyrics formatting ----------------------------------------------%
356 \override Lyrics
. LyricExtender
#'stencil
= ##f }
359 \revert Lyrics
. LyricExtender
#'stencil
}
362 \once \override LyricText
#'self-alignment-X
= #0.9 }
365 \once \override LyricHyphen
#'minimum-distance
= #4
366 \once \override LyricHyphen
#'length
= #2
367 \once \override LyricHyphen
#'thickness
= #1.2
371 \once \override LyricText
#'font-shape
= #'italic
}
374 \override LyricText
#'font-shape
= #'caps
}
377 \revert LyricText
#'font-shape
}
380 %% Scenography formatting ---------------------------------------%
382 \once \override TextScript
#'extra-spacing-width
= #'(0 . 0)
383 \once \override TextScript
#'infinite-spacing-height
= ##t
386 #(define-markup-command
(did layout props text
) (markup?
)
387 (interpret-markup layout props
388 (markup
#:override
'(line-width
. 40)
389 #:override
'(box-padding
. 1)
390 #:override
'(corner-radius
. 2)
391 #:rounded-box
#:sans
#:italic
#:small
#:justify-string text
)))
393 #(define-markup-command
(init-did layout props text
) (markup?
)
394 (interpret-markup layout props
396 ;
#:override
(cons
'line-width
(* 1 (chain-assoc-get
'line-width props
)))
398 #:override
'(line-width
. 60)
399 #:override
'(box-padding
. 1.5)
400 #:override
'(corner-radius
. 2)
401 #:rounded-box
#:sans
#:italic
#:small
#:justify-string text
))))
404 %% Table of contents --------------------------------------------%
406 #(define-music-function
(parser location text
) (markup?
)
407 (add-toc-item
! 'tocActMarkup text
))
410 #(define-music-function
(parser location text
) (markup?
)
411 (add-toc-item
! 'tocQuoteMarkup text
))
413 %% Characters and instrument names ------------------------------%
415 #(define characters `
((dummy
. "")))
416 #(define instruments `
((dummy
. "")))
418 #(define
(char-name n
) (car
(car
(assoc-get n characters
))))
419 #(define
(char-shortname n
) (cdr
(car
(assoc-get n characters
))))
420 #(define
(instr-name n
) (car
(car
(assoc-get n instruments
))))
421 #(define
(instr-shortname n
) (cdr
(car
(assoc-get n instruments
))))
423 #(define
(make-char-name n
. pad
)
424 (let
* ((txt
(char-name n
))
425 (srt
(char-shortname n
))
427 (markup
#:hcenter-in
(car pad
) txt
)
429 (n
(markup srt
))) fixme
: shortname has no padding
430 (ly
:export
(make-sequential-music
(list
431 (context-spec-music
(make-property-set
'instrumentName m
)
433 (context-spec-music
(make-property-set
'shortInstrumentName n
)
435 (context-spec-music
(make-property-set
'midiInstrument
"voice oohs")
438 #(define
(make-instrument-name n midi
. pad
)
439 (let
* ((txt
(instr-name n
))
440 (srt
(instr-shortname n
))
442 (markup
#:hcenter-in
(car pad
) txt
)
444 (n
(markup srt
))) ;; fixme
: shortname has no padding
445 (ly
:export
(make-sequential-music
(list
446 (context-spec-music
(make-property-set
'instrumentName m
)
448 (context-spec-music
(make-property-set
'shortInstrumentName n
)
450 (context-spec-music
(make-property-set
'midiInstrument midi
)