[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: TupletBrackets edge thickness
From: |
Karim Haddad |
Subject: |
Re: TupletBrackets edge thickness |
Date: |
Sat, 10 Aug 2024 19:10:55 +0200 |
Dear Lukas-Fabian,
Works like a charm. Thank you for this hack.
Thanx a lot all of you.
Best
K
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 : karim.haddad@ircam.fr
webpage : http://karim.haddad.free.fr
- Re: TupletBrackets edge thickness, (continued)
- Re: TupletBrackets edge thickness, Lukas-Fabian Moser, 2024/08/10
- Re: TupletBrackets edge thickness, Karim Haddad, 2024/08/10
- Re: TupletBrackets edge thickness, Kieren MacMillan, 2024/08/10
- Re: TupletBrackets edge thickness, Lukas-Fabian Moser, 2024/08/10
- Re: TupletBrackets edge thickness, Thomas Morley, 2024/08/11
- Re: TupletBrackets edge thickness, Karim Haddad, 2024/08/12
- Re: TupletBrackets edge thickness, Thomas Morley, 2024/08/12
- Re: TupletBrackets edge thickness, Karim Haddad, 2024/08/12
- Re: TupletBrackets edge thickness, haddad, 2024/08/12
- Re: TupletBrackets edge thickness, Thomas Morley, 2024/08/12
- Re: TupletBrackets edge thickness,
Karim Haddad <=
Re: TupletBrackets edge thickness, Karim Haddad, 2024/08/10