Hallo zusammen,
ich habe mich auch mal intensiver mit der Materie befasst, wenn auch nicht zum ersten mal. Es gibt da ein paar Fallstricke...
\version für alle Beispiele ist "2.19.45"
Idealerweise sollte ein neues Scriptzeichen einige Kriterien erfüllen:
a) Es sollte bei veränderter fontSize korrekt skaliert werden
b) Es sollte ein anders Erscheinungsbild liefern, je nachdem ob es unter oder über dem Staff steht (falls nicht onehin symmetrisch)
c) Es sollte auch für \drummode geeignet sein, falls man eine neuen drumStyleTable anlegen möchte.
Zu den Lösungsansätzen:
1. \tweak bzw \override
Diese Methode überschreibt ein bereits existierendes Zeichen.
Falls im Code enthalten ist eine Anpassung an fontSize und 'direction möglich.
Nachteile:
- Es ist natürlich nicht wirklich ein neues Zeichen
- Es ist unmöglich dieses überschriebene Zeichen in eine neue drumStyleTable zu integrieren.
2. Neuer eintrag in default-script-alist aus script.scm
Falls erfolgreich so ist das neue Scriptzeichen universel anwendbar.
Problem:
1) Script hat ein 'script-stencil property, welches einen "Verweis" auf feta enthält, sowie ein pair von strings (die aus der feta-font ausgelesen werden) zur Auswahl des glyphs für über/unter dem Staff. Elaubt sind allerdings nur script-glyphs. Natürlich werden die glyphs dann mit der passenden font-metric genommen. Eigentlich ganz nett.
Aber dies macht es unmöglich dort custom-stencils abzulegen. Es gibt auch einen check, der nur strings dort akzeptiert, ansonsten gibts einen assertion error.
2) Falls 'script-stencil ungesetzt bleibt wird auf den 'stencil zurückgefallen.
Mit dem Nachteil das man dann keine richtungsabhängige stencil definieren kann. `default-script-alist' ist erstmal nur eine Liste, von einem grob oder dessen 'direction ist hier noch nicht die Rede und man kann von dort aus auch nicht auf das grob zugreifen. Auch das skalieren des stencils ist dort nicht möglich, da man wiederum keinen Zugriff auf die aktuelle fontSize erlangen kann.
Ad 1.
Hier habe ich mal den code von fugenkomponist aufgehübscht.
#(define new-stil
(lambda (grob)
(let* ((sz (ly:grob-property grob 'font-size 0.0))
(mult (magstep sz))
(dir (ly:grob-property grob 'direction))
(thick 0.15)
(radius 0.7)
(scaled-radius (* mult radius))
(ps-command-string
(format #f
"
0 ~a translate
~a setlinewidth
~a 0 moveto
0 0 ~a 180 0 ~a
stroke
"
;mult
(* thick dir)
thick
(- scaled-radius)
scaled-radius
(if (negative? dir) "arcn" "arc"))))
(ly:make-stencil
(list 'embedded-ps
(format #f
"
gsave currentpoint translate
~a
grestore
"
ps-command-string))
(cons (- scaled-radius) scaled-radius)
(cons
(if (negative? dir) 0 (- scaled-radius))
(if (negative? dir) scaled-radius 0))))))
soft =
-\tweak stencil #new-stil
%% maybe add:
%-\tweak staff-padding #'()
\fermata
m = { c''\soft c''_\soft c''^\soft c''-> }
<<
\new Staff \with { fontSize = -6 } \m
\new Staff \with { fontSize = 0 } \m
\new Staff \with { fontSize = 6 } \m
>>
\drums {
%% override takes no effect,because there _is_ no Script-grob!
\override Script.stencil = #new-stil
bd8 bd bd2. hh1 hh2 hh4 hh8 hh cb
}
Mittels unicode wäre es:
softII =
-\tweak stencil #ly:text-interface::print
-\tweak staff-padding #'()
-\tweak text \markup \fontsize #2 \normal-text { \char ##x02D8 }
\fermata
{ c''\softII c''_\softII d''^\softII }
Man muß die font (feta-encoding für Scripts ist fetaMusic) zurücksetzen. Geht mit \normal-text.
Aber die oben beschrieben Nachteile bleiben bestehen.
Ad 2.
Hier habe ich einige stencil definiert, Setzungen für diese angegeben, mittels eines geeigneten macros in eine Kopie von `default-script-alist' eingefügt und diese dann im Score-layout angewendet.
Da die neuen script-stencils, die nicht auf feta-glyphs beruhen, nicht richtungsabhängig gemacht werden können, mußte ich an einer Stelle `arc' und `uarc' definieren.
Das Skalieren funktioniert wie schon gesagt auch nicht, insoweit kommt noch die Hilfsfunktion `scaleCustomScripts' zur Anwendung.
%% Working on a copy of `default-script-alist´ should warrant no bleed-over.
#(define my-script-alist (list-copy default-script-alist))
%% Some custom stencils
#(define ellipse-stil
(ly:stencil-in-color
(make-partial-ellipse-stencil 1 0.3 2 2 0.13 #t #f)
1 0 0))
%% Code taken from
%% https://liarchiv.joonet.de/index.php?topic=1279.msg7040#msg7040
%% by Torsten and modified
#(define (n-agon-stil nmbr)
(let* ((th 0.1)
;; Value @code{6} returns a hexagon.
(alpha-step (/ (* 2 PI) nmbr))
(alpha-start (/ alpha-step 2))
(radius 0.7)
(polypoints
(let loop ((alpha alpha-start))
(if (> alpha (* 2 PI))
'()
(cons (* (abs radius) (sin alpha))
(cons (- 0 (* (abs radius) (cos alpha)))
(loop (+ alpha alpha-step))))))))
(ly:make-stencil
`(polygon ',polypoints ,th #f)
(cons (- radius) radius)
(cons (- radius) radius))))
#(define (bezier-arc-stil direction)
(make-connected-path-stencil
`((0.15 ,direction 1.05 ,direction 1.2 0)) 0.2 1 1 #f #f))
%% Alists with the name of the new articulation and its settings.
#(define varsegno-settings
`("varsegno"
. (
(script-stencil . (feta . ("varsegno" . "varsegno")))
(padding . 0.20)
(avoid-slur . outside)
(direction . ,UP))))
#(define ellipse-settings
`("ellipse"
. (
(avoid-slur . around)
(padding . 0.20)
(side-relative-direction . ,DOWN)
(stencil . ,ellipse-stil))))
#(define hexagon-settings
`("hexagon"
. (
(avoid-slur . around)
(padding . 0.20)
(stencil . ,(n-agon-stil 6))
(side-relative-direction . ,DOWN))))
#(define arc-settings
`("arc"
. (
(avoid-slur . around)
(padding . 0.20)
(stencil . ,(bezier-arc-stil -1))
(side-relative-direction . ,DOWN))))
#(define up-arc-settings
`("uarc"
. (
(avoid-slur . around)
(padding . 0.20)
(stencil . ,(bezier-arc-stil 1))
(side-relative-direction . ,DOWN))))
%% A macro used to put the lists from above in `my-script-alist´
#(define-macro (set-my-script-alist! ls-1 ls-2)
"Creates a new key-value-pair, taken from ls-2, in ls-1"
`(set! ,ls-1
(if (and (pair? ,ls-2) (pair? (cadr ,ls-2)))
(assoc-set! ,ls-1 (car ,ls-2) (cdr ,ls-2))
(begin
(ly:warning (_"Unsuitable list\n\t~a \n\tdetected, ignoring. ") ,ls-2)
,ls-1))))
%% put the new articulations into `my-script-alist'
#(for-each
(lambda (l)
(set-my-script-alist! my-script-alist l))
(list
varsegno-settings
ellipse-settings
hexagon-settings
arc-settings
up-arc-settings))
%% `script-stencil' used for script-settings in script.scm looks for glyphs in
%% a font (feta), only explicit script-glyphs are accepted. The glyphs found are
%% scaled(?) to fit the current `fontSize'. This seems to make it impossible to
%% put in there custom-stencils created by a procedure. There are checks to
%% ensure strings to be in there. Also, if script-stencil is empty one should
%% fall back to stencil, which makes it impossible to get stencils with
%% different appearance for UP/DOWN, instead one has to define different
%% stencils for this purpose.
%% Anyway, here a workaround to get at least the scaling better.
scaleCustomScripts =
\override Script.before-line-breaking =
#(lambda (grob)
(let* ((script-stencil (ly:grob-property grob 'script-stencil)))
(if (null? script-stencil)
(let* ((sz (ly:grob-property grob 'font-size 0.0))
(mult (magstep sz)))
(ly:grob-set-property! grob 'stencil
(ly:stencil-scale
(ly:grob-property grob 'stencil)
mult
mult))))))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Examples
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\header {
title = "New Scripts"
subtitle = "for"
subsubtitle = "\\drummode and \\notemode"
meter =
\markup \fill-line {
"defined are ellipse, hexagon, varsegno, arc and uarc"
}
}
%% To use the new scripts call `my-script-alist' in \layout
%% Scale them accordingly
\layout {
\context {
\Score
scriptDefinitions = #my-script-alist
\scaleCustomScripts
}
}
%%%%
%%%% default \notemode
%%%%
ellipse = #(make-articulation "ellipse")
hexagon = #(make-articulation "hexagon")
arc = #(make-articulation "arc")
uarc = #(make-articulation "uarc")
varsegno = #(make-articulation "varsegno")
%% Shortcuts.
%% TODO: How to create more shortcuts?
%% Below are redefined ones.
dashDash = "ellipse"
dashHat = "hexagon"
mus =
\relative c' {
c1-\ellipse d^\ellipse
e-\hexagon f^\hexagon
c'1-- d_-
e-^ f_^
c-\arc
c_\arc
c^\arc
c-\uarc
c_\uarc
c^\uarc
c_\varsegno
}
<<
\new Staff \with { fontSize = -6 } \mus
\new Staff \with { fontSize = 0 } \mus
\new Staff \with { fontSize = 6 } \mus
>>
%%%%
%%%% \drummode
%%%%
%% A new drum-table
#(define mydrums
'((bassdrum laThin "ellipse" -1)
(hihat laThin "hexagon" 3)
(closedhihat cross "stopped" 3)
(cowbell triangle "arc" 5)))
\layout {
\context {
\DrumStaff
\override StaffSymbol #'line-count = #2
drumStyleTable = #(alist->hash-table mydrums)
}
}
drum-mus = \drummode { bd8 bd bd2. hh1 hh2 hh4 hh8 hh cb }
<<
\new DrumStaff \with { fontSize = #-6 } \drum-mus
\new DrumStaff \with { fontSize = #0 } \drum-mus
\new DrumStaff \with { fontSize = #6 } \drum-mus
>>
Das ist natürlich ziemlich aufwendig, fumktioniert jetzt aber sowohl mit \notemode als auch mit \drummode.
Ich überlege eine feature-request zu schreiben, damit das Ganze etwas besser und angenehmer wird. Da ist aber auch in C++ zu kodieren. Insoweit kann ich es nicht selber machen, C++ kann ich nicht...
Komplettes file und png auch im Anhang.
HTH,
Harm