3 text-spanner.cc -- implement Text_spanner
5 source file of the GNU LilyPond music typesetter
7 (c) 2000--2003 Jan Nieuwenhuizen <janneke@gnu.org>
10 #include "molecule.hh"
11 #include "text-item.hh"
12 #include "text-spanner.hh"
13 #include "line-spanner.hh"
15 #include "font-interface.hh"
16 #include "dimensions.hh"
17 #include "paper-def.hh"
19 #include "paper-column.hh"
20 #include "staff-symbol-referencer.hh"
24 - vertical start / vertical end (fixme-name) |
25 - contination types (vert. star, vert. end) |-> eat volta-bracket
27 - more texts/positions
30 MAKE_SCHEME_CALLBACK (Text_spanner
, brew_molecule
, 1);
33 TODO: this function is too long
36 Text_spanner::brew_molecule (SCM smob
)
38 Grob
*me
= unsmob_grob (smob
);
39 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
41 if (spanner
->internal_has_interface (ly_symbol2scm ("piano-pedal-interface")))
43 setup_pedal_bracket(spanner
);
46 /* Ugh, must be same as Hairpin::brew_molecule. */
48 SCM itp
= me
->get_grob_property ("if-text-padding");
49 if (gh_number_p (itp
))
50 padding
= gh_scm2double (itp
);
52 Grob
*common
= spanner
->get_bound (LEFT
)->common_refpoint (spanner
->get_bound (RIGHT
), X_AXIS
);
55 Drul_array
<bool> broken
;
59 Item
*b
= spanner
->get_bound (d
);
60 broken
[d
] = b
->break_status_dir () != CENTER
;
65 span_points
[d
] = spanner
->get_broken_left_end_align ();
67 span_points
[d
] = b
->relative_coordinate (common
, X_AXIS
);
71 bool encl
= to_boolean (me
->get_grob_property ("enclose-bounds"));
72 span_points
[d
] = b
->extent (common
, X_AXIS
)[encl
? d
: -d
];
75 while (flip (&d
) != LEFT
);
80 FIXME. - this switch sucks. --hwn
82 // FIXME: ecs tells us -- only for (de)cresc. spanners
83 width
+= gh_scm2double (me
->get_grob_property ("width-correct"));
86 SCM properties
= Font_interface::font_alist_chain (me
);
87 SCM edge_text
= me
->get_grob_property ("edge-text");
88 Drul_array
<Molecule
> edge
;
89 if (gh_pair_p (edge_text
))
94 /* Don't repeat edge text for broken end */
98 SCM text
= index_get_cell (edge_text
, d
);
104 edge
[d
] = Text_item::interpret_new_markup (smob
, properties
, text
);
105 if (!edge
[d
].empty_b ())
106 edge
[d
].align_to (Y_AXIS
, CENTER
);
108 while (flip (&d
) != LEFT
);
112 Drul_array
<Real
> shorten
;
116 SCM s
= me
->get_grob_property ("shorten-pair");
119 span_points
[LEFT
] += gh_scm2double (ly_car (s
));
120 span_points
[RIGHT
] -= gh_scm2double (ly_cdr (s
));
123 Real thick
= me
->get_paper ()->get_var ("linethickness");
124 SCM st
= me
->get_grob_property ("thickness");
125 if (gh_number_p (st
))
127 thick
*= gh_scm2double (st
);
130 Drul_array
<Molecule
> edge_line
;
131 s
= me
->get_grob_property ("edge-height");
132 SCM ew
= me
->get_grob_property ("edge-widen");
136 int dir
= to_dir (me
->get_grob_property ("direction"));
144 dx
= gh_scm2double (index_get_cell (ew
, d
)) * d
;
146 Real dy
= gh_scm2double (index_get_cell (s
, d
)) * - dir
;
148 edge_line
[d
] = Line_spanner::line_molecule (me
, thick
, dx
, dy
);
150 while (flip (&d
) != LEFT
);
156 Interval ext
= edge
[d
].extent (X_AXIS
);
158 edge
[d
].translate_axis (span_points
[d
], X_AXIS
);
159 m
.add_molecule (edge
[d
]);
160 edge_line
[d
].translate_axis (span_points
[d
], X_AXIS
);
161 m
.add_molecule (edge_line
[d
]);
163 span_points
[d
] += -d
* ext
[-d
];
165 while (flip (&d
) != LEFT
);
167 Molecule l
=Line_spanner::line_molecule (me
, thick
,
168 span_points
.length (), 0);
169 l
.translate_axis (span_points
[LEFT
], X_AXIS
);
172 m
.translate_axis (- me
->relative_coordinate (common
, X_AXIS
), X_AXIS
);
173 return m
.smobbed_copy ();
180 Piano pedal brackets are a special case of a text spanner.
181 Pedal up-down (restart) indicated by the angled right and left edges
182 of consecutive pedals touching exactly to form an __/\__
183 Chris Jackson <chris@fluffhouse.org.uk>
186 TODO: this should be moved somewhere else (?).
188 Perhaps make separate function for pedal-bracket.
193 This is broken broken.
195 All the tweak props should be unnecessary.
197 This should not be linked with Text_spanner.
201 Text_spanner::setup_pedal_bracket(Spanner
*me
)
204 Real thick
= me
->get_paper ()->get_var ("linethickness");
205 SCM st
= me
->get_grob_property ("thickness");
206 if (gh_number_p (st
))
208 thick
*= gh_scm2double (st
);
211 Drul_array
<bool> broken
;
212 Drul_array
<Real
> height
, width
, shorten
, r
;
214 SCM pa
= me
->get_grob_property ("if-text-padding");
215 SCM ew
= me
->get_grob_property ("edge-widen");
216 SCM eh
= me
->get_grob_property ("edge-height");
217 SCM sp
= me
->get_grob_property ("shorten-pair");
223 if (gh_number_p (pa
))
224 padding
= gh_scm2double (pa
);
228 Item
*b
= me
->get_bound (d
);
230 e
= b
->extent (b
, X_AXIS
);
232 r
[d
] = d
* (e
[-d
] + padding
);
234 broken
[d
] = b
->break_status_dir () != CENTER
;
238 if (ly_number_pair_p (ew
))
239 width
[d
] += gh_scm2double (index_get_cell (ew
, d
));
240 if (!broken
[d
] && (ly_number_pair_p (eh
)))
241 height
[d
] += gh_scm2double (index_get_cell (eh
, d
));
242 if (ly_number_pair_p (sp
))
243 shorten
[d
] += gh_scm2double (index_get_cell (sp
, d
));
245 while (flip (&d
) != LEFT
);
247 Real extra_short
= 0;
248 // For 'Mixed' style pedals, i.e. a bracket preceded by text: Ped._____|
249 // need to shorten by the extent of the text grob
250 if (to_boolean (me
->get_grob_property ("text-start")))
253 extra_short
= padding
;
254 if (Grob
*textbit
= unsmob_grob (me
->get_grob_property("pedal-text")))
256 if (textbit
->internal_has_interface(ly_symbol2scm("text-interface")))
257 // for plain text, e.g., Sost. Ped.
259 SCM text
= textbit
->get_grob_property("text");
260 if (gh_string_p (text
)) {
261 SCM properties
= Font_interface::font_alist_chain (me
);
263 Molecule mol
= Text_item::interpret_new_markup (me
->self_scm (),
265 extra_short
+= mol
.extent(X_AXIS
).length() / 2;
269 shorten
[RIGHT
] -= thick
;
272 shorten
[LEFT
] += extra_short
;
276 shorten
[LEFT
] -= me
->get_broken_left_end_align () ;
277 shorten
[RIGHT
] += abs(width
[RIGHT
]) + thick
- r
[RIGHT
];
282 // Shorten a ____/ on the right so that it will touch an adjoining \___
283 shorten
[RIGHT
] += abs(width
[LEFT
]) + abs(width
[RIGHT
]) + thick
;
284 // Also shorten so that it ends just before the spanned note.
285 shorten
[RIGHT
] -= (r
[LEFT
] + r
[RIGHT
]);
288 me
->set_grob_property ("edge-height", ly_interval2scm (height
));
289 me
->set_grob_property ("edge-widen", ly_interval2scm(width
));
290 me
->set_grob_property ("shorten-pair", ly_interval2scm (shorten
));
296 static bool has_interface (Grob
*);
298 ADD_INTERFACE (Pianopedal
,"piano-pedal-interface",
300 "pedal-type edge-widen edge-height shorten-pair text-start left-widen right-widen pedal-text");
302 ADD_INTERFACE (Text_spanner
,"text-spanner-interface",
303 "generic text spanner",
304 "dash-period if-text-padding dash-length edge-height edge-widen edge-text shorten-pair style thickness enclose-bounds width-correct");