Thank you Lukas-Fabian for all this precious info. Will test this for sure.
Best regards Karim On Sat, Aug 10, 2024 at 02:17:07PM +0200, Lukas-Fabian Moser wrote: > Hi Kieren, hi Karim, > > Am 09.08.24 um 16:40 schrieb Kieren MacMillan: > > > Just trying to find out how to manage the thickness of the edges of > > > tupletbrackets and if this is possible (cf. screenshot). In the > > > documentation we can adjust the thickness of the whole bracket but not > > > just the edges. Any idea? > > I would imagine that either TupletBracket.edge-text or > > TupletBracket.stencil could be tweaked… Unfortunately I’ve spent 15 minutes > > and can’t find the magic incantation — hopefully someone else can! > > Well, trying to teach how to fish :-): > > In the Internals Reference > https://lilypond.org/doc/v2.23/Documentation/internals/tupletbracket we see > that the TupletBracket stencil is ly:tuplet-bracket::print. Moving to the > source, git grep "tuplet-bracket::print" on the command line yields: > > Documentation/ly-examples/stockhausen-klavierstueckII.ly: > (ly:tuplet-bracket::print grob))) > lily/tuplet-bracket.cc:MAKE_SCHEME_CALLBACK (Tuplet_bracket, print, > "ly:tuplet-bracket::print", 1); > scm/define-grobs.scm: (stencil . ,ly:tuplet-bracket::print) > scm/define-grobs.scm: (stencil . ,ly:tuplet-bracket::print) > > The second line shows that the procedure is in the C++ part of LilyPond > (alas...); the third and fourth lines show _two_ grobs using this procedure > as stencil. (Reading in scm/define-grobs.scm reveals that the other one > besides TupletBracket is LigatureBracket). > > Now in lily/tuplet-bracket.cc we find: > > MAKE_SCHEME_CALLBACK (Tuplet_bracket, print, "ly:tuplet-bracket::print", 1); > SCM > Tuplet_bracket::print (SCM smob) > { > Spanner *me = LY_ASSERT_SMOB (Spanner, smob, 1); > Stencil mol; > > bool tuplet_slur = scm_is_true (get_property (me, "tuplet-slur")); > > bool bracket_visibility = bracket_basic_visibility (me); > SCM bracket_vis_prop = get_property (me, "bracket-visibility"); > > /* > Don't print a tuplet bracket and number if > no X or Y positions were calculated. > */ > SCM scm_x_span = get_property (me, "X-positions"); > SCM scm_positions = get_property (me, "positions"); > if (!scm_is_pair (scm_x_span) || !scm_is_pair (scm_positions)) > { > me->suicide (); > return SCM_EOL; > } > > Interval x_span = from_scm (scm_x_span, Interval (0.0, 0.0)); > Interval positions = from_scm (scm_positions, Interval (0.0, 0.0)); > > Drul_array<Offset> points; > for (const auto d : {LEFT, RIGHT}) > points[d] = Offset (x_span[d], positions[d]); > > Grob *number_grob = unsmob<Grob> (get_object (me, "tuplet-number")); > > /* > Don't print the bracket when it would be smaller than the number. > ...Unless the user has coded bracket-visibility = #t, that is. > */ > > Real gap = 0.; > if (bracket_visibility && number_grob) > { > Interval ext = number_grob->extent (number_grob, X_AXIS); > if (!ext.is_empty ()) > { > gap = ext.length () + 1.0; > > if (!from_scm<bool> (bracket_vis_prop) && gap > x_span.length ()) > bracket_visibility = false; > } > } > > if (bracket_visibility) > { > Drul_array<Real> zero (0, 0); > > Drul_array<Real> shorten > = from_scm (get_property (me, "shorten-pair"), zero); > > Real ss = Staff_symbol_referencer::staff_space (me); > scale_drul (&shorten, ss); > > Stencil brack; > > if (tuplet_slur) > { > brack = make_tuplet_slur (me, points[LEFT], points[RIGHT], > shorten); > mol.add_stencil (brack); > } > else > { > * Drul_array<Stencil> edge_stencils; > * > Drul_array<Real> height > = from_scm (get_property (me, "edge-height"), zero); > Drul_array<Real> flare > = from_scm (get_property (me, "bracket-flare"), zero); > Direction dir = get_grob_direction (me); > > scale_drul (&height, -ss * dir); > scale_drul (&flare, ss); > > const auto connect_to_other = from_scm ( > get_property (me, "connect-to-neighbor"), Drul_array<bool> ()); > > * for (const auto d : {LEFT, RIGHT}) > * { > * if (connect_to_other[d]) > * { > * height[d] = 0.0; > flare[d] = 0.0; > shorten[d] = 0.0; > * > * SCM edge_text = get_property (me, "edge-text"); > * > if (scm_is_pair (edge_text)) > { > * SCM text = index_get_cell (edge_text, d); > * if (Text_interface::is_markup (text)) > { > * auto &es = edge_stencils[d]; > es = Text_interface::grob_interpret_markup (me, > text); > * es.translate_axis (x_span[d] - x_span[LEFT], > X_AXIS); > } > } > } > } > > Stencil brack; > if (tuplet_slur) > brack = make_tuplet_slur (me, points[LEFT], points[RIGHT], > shorten); > else > *brack = Bracket::make_bracket ( > me, Y_AXIS, points[RIGHT] - points[LEFT], height, > /* > 0.1 = more space at right due > to italics > TODO: use italic correction of > font. > */ > Interval (-0.5, 0.5) * gap + 0.1, flare, shorten);* > > for (const auto d : {LEFT, RIGHT}) > { > if (!edge_stencils[d].is_empty ()) > *brack.add_stencil (edge_stencils[d])*; > } > > mol.add_stencil (brack); > mol.translate (points[LEFT]); > } > } > return mol.smobbed_copy (); > } > > I highlighted the relevant lines in bold face. These show that edge-text is > only being used for TupletBrackets that connect to their neighbors (i.e. > broken TupletBracket grobs), which can also be observed in the regression > test input/regression/tuplet-broken.ly). I admit that this is not so clear > from reading the description of edge-text in > https://lilypond.org/doc/v2.23/Documentation/internals/tuplet_002dbracket_002dinterface > ... > > So in any case: The bracket itself gets drawn by Bracket::make_bracket, > which has the following signature (found in lily/bracket.cc): > > Stencil > Bracket::make_bracket (Grob *me, // for line properties. > Axis protrusion_axis, Offset dz, Drul_array<Real> > height, > Interval gap, Drul_array<Real> flare, > Drul_array<Real> shorten) > > So there's no parameter for thickness only for the side lines, and indeed > line properties are taken from the grob itself for all three lines. > Conclusion: There's no easy way to influence the way the bracket is drawn. > > So we have to do something else. One brute-force possibility would be to > just crack the finished stencil open and change the line width of the edge > lines. If we look at the stencil expression of a TupletBracket, using > > \version "2.24.0" > > { > \override TupletBracket.stencil = > #(grob-transformer 'stencil > (lambda (grob stil) > (pretty-print (ly:stencil-expr stil)) > stil)) > > \tuplet 3/2 { c'4 d' c''' } > } > > we find: > > (translate-stencil > (1.1742119999999971 . 3.954403577019947) > (combine-stencil > (draw-line > 0.16 > 5.465341561078519 > 2.323245692493028 > 5.465341561078519 > 1.6232456924930279) > (draw-line > 0.16 > -0.1840604182213724 > -0.07824169249302755 > -0.1840604182213724 > -0.7782416924930275) > (draw-line > 0.16 > 5.465341561078519 > 2.323245692493028 > 3.632732022820297 > 1.544227186842694) > (draw-line > 0.16 > -0.1840604182213724 > -0.07824169249302755 > 1.8326095382582217 > 0.7790185056503338))) > > This looks as if the left and right line are the first two lines in the > stencil (those have constant x coordinates). This aligns with the definition > of make_bracket that adds the corner stencils first. > > So we might do: > > \version "2.24.0" > > { > \override TupletBracket.stencil = > #(grob-transformer 'stencil > (lambda (grob stil) > (let* > ((expr (ly:stencil-expr stil)) > (xext (ly:stencil-extent stil X)) > (yext (ly:stencil-extent stil Y)) > (lines (cdaddr expr)) > (line1 (first lines)) > (line2 (second lines))) > > (list-set! line1 1 0.5) > (list-set! line2 1 0.5) > > (ly:make-stencil expr xext yext)))) > > \tuplet 3/2 { c'4 d' c''' } > \tuplet 3/2 { c'4 d' e' } > } > > But note that this is a) an dirty hack since it assumes that the > TupletBracket stencil always comes in the form we expect, b) not yet ideal > since the rounded lines still have to be moved down. At least the second > issue can be remedied: > > \version "2.24.0" > > { > \override TupletBracket.stencil = > #(grob-transformer 'stencil > (lambda (grob stil) > (let* > ((expr (ly:stencil-expr stil)) > (xext (ly:stencil-extent stil X)) > (yext (ly:stencil-extent stil Y)) > (lines (cdaddr expr)) > (line1 (first lines)) > (thick (second line1)) > (new-thick 0.6) ;; adjust at will > (offset (/ (- new-thick thick) 2)) > (line2 (second lines))) > > (list-set! line1 1 new-thick) > (list-set! line2 1 new-thick) > > (list-set! line1 3 (- (list-ref line1 3) offset)) > (list-set! line2 3 (- (list-ref line2 3) offset)) > > (ly:make-stencil expr xext yext)))) > > \tuplet 3/2 { c'4 d' c''' } > \tuplet 3/2 { c'4 d' e' } > } > > Left to do: We probably also should modify the extents of the resulting > stencil to avoid collisions... > > Lukas -- Karim Haddad Music Representations Team, IRCAM Research and development manager. email : [email protected] webpage : http://karim.haddad.free.fr
