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
);
103 edge
[d
] = Text_item::text2molecule (me
, text
, properties
);
104 if (!edge
[d
].empty_b ())
105 edge
[d
].align_to (Y_AXIS
, CENTER
);
107 while (flip (&d
) != LEFT
);
111 Drul_array
<Real
> shorten
;
115 SCM s
= me
->get_grob_property ("shorten-pair");
118 span_points
[LEFT
] += gh_scm2double (ly_car (s
));
119 span_points
[RIGHT
] -= gh_scm2double (ly_cdr (s
));
122 Real thick
= me
->get_paper ()->get_var ("linethickness");
123 SCM st
= me
->get_grob_property ("thickness");
124 if (gh_number_p (st
))
126 thick
*= gh_scm2double (st
);
129 Drul_array
<Molecule
> edge_line
;
130 s
= me
->get_grob_property ("edge-height");
131 SCM ew
= me
->get_grob_property ("edge-widen");
135 int dir
= to_dir (me
->get_grob_property ("direction"));
143 dx
= gh_scm2double (index_get_cell (ew
, d
)) * d
;
145 Real dy
= gh_scm2double (index_get_cell (s
, d
)) * - dir
;
147 edge_line
[d
] = Line_spanner::line_molecule (me
, thick
, dx
, dy
);
149 while (flip (&d
) != LEFT
);
155 Interval ext
= edge
[d
].extent (X_AXIS
);
157 edge
[d
].translate_axis (span_points
[d
], X_AXIS
);
158 m
.add_molecule (edge
[d
]);
159 edge_line
[d
].translate_axis (span_points
[d
], X_AXIS
);
160 m
.add_molecule (edge_line
[d
]);
162 span_points
[d
] += -d
* ext
[-d
];
164 while (flip (&d
) != LEFT
);
166 Molecule l
=Line_spanner::line_molecule (me
, thick
,
167 span_points
.length (), 0);
168 l
.translate_axis (span_points
[LEFT
], X_AXIS
);
171 m
.translate_axis (- me
->relative_coordinate (common
, X_AXIS
), X_AXIS
);
172 return m
.smobbed_copy ();
179 Piano pedal brackets are a special case of a text spanner.
180 Pedal up-down (restart) indicated by the angled right and left edges
181 of consecutive pedals touching exactly to form an __/\__
182 Chris Jackson <chris@fluffhouse.org.uk>
185 TODO: this should be moved somewhere else (?).
187 Perhaps make separate function for pedal-bracket.
191 Text_spanner::setup_pedal_bracket(Spanner
*me
)
194 Real thick
= me
->get_paper ()->get_var ("linethickness");
195 SCM st
= me
->get_grob_property ("thickness");
196 if (gh_number_p (st
))
198 thick
*= gh_scm2double (st
);
201 Drul_array
<bool> broken
;
202 Drul_array
<Real
> height
, width
, shorten
, r
;
204 SCM pa
= me
->get_grob_property ("if-text-padding");
205 SCM ew
= me
->get_grob_property ("edge-widen");
206 SCM eh
= me
->get_grob_property ("edge-height");
207 SCM sp
= me
->get_grob_property ("shorten-pair");
213 if (gh_number_p (pa
) )
214 padding
= gh_scm2double (pa
);
218 Item
*b
= me
->get_bound (d
);
220 e
= b
->extent (b
, X_AXIS
);
222 r
[d
] = d
* (e
[-d
] + padding
);
224 broken
[d
] = b
->break_status_dir () != CENTER
;
228 if ( ly_number_pair_p (ew
) )
229 width
[d
] += gh_scm2double (index_get_cell (ew
, d
));
230 if ( !broken
[d
] && (ly_number_pair_p (eh
) ) )
231 height
[d
] += gh_scm2double (index_get_cell (eh
, d
));
232 if ( ly_number_pair_p (sp
) )
233 shorten
[d
] += gh_scm2double (index_get_cell (sp
, d
));
235 while (flip (&d
) != LEFT
);
237 Real extra_short
= 0;
238 // For 'Mixed' style pedals, i.e. a bracket preceded by text: Ped._____|
239 // need to shorten by the extent of the text grob
240 if ( to_boolean (me
->get_grob_property ("text-start")) )
243 extra_short
= padding
;
244 if (Grob
*textbit
= unsmob_grob (me
->get_grob_property("pedal-text")))
246 if (textbit
->internal_has_interface(ly_symbol2scm("text-interface")))
247 // for plain text, e.g., Sost. Ped.
249 SCM text
= textbit
->get_grob_property("text");
250 if (gh_string_p (text
)) {
251 SCM properties
= Font_interface::font_alist_chain (me
);
252 Molecule mol
= Text_item::text2molecule (me
, text
, properties
);
253 extra_short
+= mol
.extent(X_AXIS
).length() / 2;
257 shorten
[RIGHT
] -= thick
;
260 shorten
[LEFT
] += extra_short
;
264 shorten
[LEFT
] -= me
->get_broken_left_end_align () ;
265 shorten
[RIGHT
] += abs(width
[RIGHT
]) + thick
- r
[RIGHT
];
270 // Shorten a ____/ on the right so that it will touch an adjoining \___
271 shorten
[RIGHT
] += abs(width
[LEFT
]) + abs(width
[RIGHT
]) + thick
;
272 // Also shorten so that it ends just before the spanned note.
273 shorten
[RIGHT
] -= (r
[LEFT
] + r
[RIGHT
]);
276 me
->set_grob_property ("edge-height", ly_interval2scm (height
));
277 me
->set_grob_property ("edge-widen", ly_interval2scm(width
));
278 me
->set_grob_property ("shorten-pair", ly_interval2scm (shorten
));
284 static bool has_interface (Grob
*);
286 ADD_INTERFACE (Pianopedal
,"piano-pedal-interface",
288 "pedal-type edge-widen edge-height shorten-pair text-start left-widen right-widen pedal-text");
290 ADD_INTERFACE (Text_spanner
,"text-spanner-interface",
291 "generic text spanner",
292 "dash-period if-text-padding dash-length edge-height edge-widen edge-text shorten-pair type thickness enclose-bounds width-correct");