Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / lyric-extender.cc
blob088881fc1dd5c9ffe2a7922c5af924493a5a2bef
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2011 Jan Nieuwenhuizen <janneke@gnu.org>
5 Han-Wen Nienhuys
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "lyric-extender.hh"
23 #include "system.hh"
24 #include "item.hh"
25 #include "warn.hh"
26 #include "lookup.hh"
27 #include "output-def.hh"
28 #include "note-head.hh"
29 #include "pointer-group-interface.hh"
31 MAKE_SCHEME_CALLBACK (Lyric_extender, print, 1);
32 SCM
33 Lyric_extender::print (SCM smob)
35 Spanner *me = unsmob_spanner (smob);
36 Item *left_edge = me->get_bound (LEFT);
37 Item *right_text = unsmob_item (me->get_object ("next"));
39 Grob *common = left_edge;
41 if (right_text)
42 common = common->common_refpoint (right_text, X_AXIS);
44 common = common->common_refpoint (me->get_bound (RIGHT), X_AXIS);
45 common = common->common_refpoint (me->get_system (), X_AXIS);
47 Real sl = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
49 extract_grob_set (me, "heads", heads);
51 if (!heads.size ())
52 return SCM_EOL;
54 common = common_refpoint_of_array (heads, common, X_AXIS);
56 Real left_point = 0.0;
57 if (left_edge->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
58 left_point = left_edge->extent (common, X_AXIS)[RIGHT];
59 else if (heads.size ())
60 left_point = heads[0]->extent (common, X_AXIS)[LEFT];
61 else
62 left_point = left_edge->extent (common, X_AXIS)[RIGHT];
64 if (isinf (left_point))
65 return SCM_EOL;
67 /* It seems that short extenders are even lengthened to go past the
68 note head, but haven't found a pattern in it yet. --hwn 1/1/04 */
69 SCM minlen = me->get_property ("minimum-length");
70 Real right_point
71 = left_point + (robust_scm2double (minlen, 0));
73 right_point = min (right_point, me->get_system ()->get_bound (RIGHT)->relative_coordinate (common, X_AXIS));
75 if (heads.size ())
76 right_point = max (right_point, heads.back ()->extent (common, X_AXIS)[RIGHT]);
78 Real h = sl * robust_scm2double (me->get_property ("thickness"), 0);
79 Drul_array<Real> paddings (robust_scm2double (me->get_property ("left-padding"), h),
80 robust_scm2double (me->get_property ("right-padding"), h));
82 if (right_text)
83 right_point = min (right_point, (robust_relative_extent (right_text, common, X_AXIS)[LEFT] - paddings[RIGHT]));
85 /* run to end of line. */
86 if (me->get_bound (RIGHT)->break_status_dir ())
87 right_point = max (right_point, (robust_relative_extent (me->get_bound (RIGHT), common, X_AXIS)[LEFT] - paddings[RIGHT]));
89 left_point += paddings[LEFT];
90 Real w = right_point - left_point;
92 if (w < 1.5 * h)
93 return SCM_EOL;
95 Stencil mol (Lookup::round_filled_box (Box (Interval (0, w),
96 Interval (0, h)),
97 0.8 * h));
98 mol.translate_axis (left_point - me->relative_coordinate (common, X_AXIS),
99 X_AXIS);
100 return mol.smobbed_copy ();
103 ADD_INTERFACE (Lyric_extender,
104 "The extender is a simple line at the baseline of the lyric"
105 " that helps show the length of a melisma (a tied or slurred"
106 " note).",
108 /* properties */
109 "heads "
110 "left-padding "
111 "next "
112 "right-padding "
113 "thickness "