2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1996--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 Jan Nieuwenhuizen <janneke@gnu.org>
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/>.
23 #include "directional-element-interface.hh"
24 #include "font-interface.hh"
26 #include "international.hh"
27 #include "output-def.hh"
28 #include "staff-symbol-referencer.hh"
35 DECLARE_SCHEME_CALLBACK (print, (SCM));
36 DECLARE_SCHEME_CALLBACK (glyph_name, (SCM));
37 DECLARE_SCHEME_CALLBACK (width, (SCM));
38 DECLARE_SCHEME_CALLBACK (calc_y_offset, (SCM));
39 DECLARE_SCHEME_CALLBACK (pure_calc_y_offset, (SCM, SCM, SCM));
40 DECLARE_SCHEME_CALLBACK (calc_x_offset, (SCM));
41 DECLARE_GROB_INTERFACE ();
43 static SCM internal_calc_y_offset (SCM smob, bool pure);
46 MAKE_SCHEME_CALLBACK (Flag, width, 1);
48 Flag::width (SCM smob)
50 Grob *me = unsmob_grob (smob);
51 Stencil *sten = unsmob_stencil (me->get_property ("stencil"));
53 return ly_interval2scm (Interval (0.0, 0.0));
55 Grob *stem = me->get_parent (X_AXIS);
59 This reproduces a bad hard-coding that has been in the code for quite some time:
60 the bounding boxes for the flags are slightly off and need to be fixed.
63 return ly_interval2scm (sten->extent (X_AXIS) - stem->extent (stem, X_AXIS)[RIGHT]);
66 MAKE_SCHEME_CALLBACK (Flag, glyph_name, 1);
68 Flag::glyph_name (SCM smob)
70 Grob *me = unsmob_grob (smob);
71 Grob *stem = me->get_parent (X_AXIS);
73 Direction d = get_grob_direction (stem);
74 int log = Stem::duration_log (stem);
77 SCM flag_style_scm = me->get_property ("style");
78 if (scm_is_symbol (flag_style_scm))
79 flag_style = ly_symbol2string (flag_style_scm);
83 string staffline_offs;
84 if (flag_style == "mensural")
85 /* Mensural notation: For notes on staff lines, use different
86 flags than for notes between staff lines. The idea is that
87 flags are always vertically aligned with the staff lines,
88 regardless if the note head is on a staff line or between two
89 staff lines. In other words, the inner end of a flag always
95 Real ss = Staff_symbol_referencer::staff_space (me);
96 int p = (int) (rint (stem->extent (stem, Y_AXIS)[d] * 2 / ss));
98 = Staff_symbol_referencer::on_line (stem, p) ? "0" : "1";
101 staffline_offs = "2";
106 char dir = (d == UP) ? 'u' : 'd';
107 string font_char = flag_style
108 + ::to_string (dir) + staffline_offs + ::to_string (log);
109 return ly_string2scm ("flags." + font_char);
112 MAKE_SCHEME_CALLBACK (Flag, print, 1);
114 Flag::print (SCM smob)
116 Grob *me = unsmob_grob (smob);
117 Grob *stem = me->get_parent (X_AXIS);
119 Direction d = get_grob_direction (stem);
122 SCM flag_style_scm = me->get_property ("style");
123 if (scm_is_symbol (flag_style_scm))
124 flag_style = ly_symbol2string (flag_style_scm);
126 if (flag_style == "no-flag")
127 return Stencil ().smobbed_copy ();
129 char dir = (d == UP) ? 'u' : 'd';
130 Font_metric *fm = Font_interface::get_default_font (me);
131 string font_char = robust_scm2string (me->get_property ("glyph-name"), "");
132 Stencil flag = fm->find_by_name (font_char);
133 if (flag.is_empty ())
134 me->warning (_f ("flag `%s' not found", font_char));
137 TODO: maybe property stroke-style should take different values,
138 e.g. "" (i.e. no stroke), "single" and "double" (currently, it's
140 SCM stroke_style_scm = me->get_property ("stroke-style");
141 if (scm_is_string (stroke_style_scm))
143 string stroke_style = ly_scm2string (stroke_style_scm);
144 if (!stroke_style.empty ())
146 string font_char = flag_style + ::to_string (dir) + stroke_style;
147 Stencil stroke = fm->find_by_name ("flags." + font_char);
148 if (stroke.is_empty ())
150 font_char = ::to_string (dir) + stroke_style;
151 stroke = fm->find_by_name ("flags." + font_char);
153 if (stroke.is_empty ())
154 me->warning (_f ("flag stroke `%s' not found", font_char));
156 flag.add_stencil (stroke);
160 return flag.smobbed_copy ();
163 MAKE_SCHEME_CALLBACK (Flag, pure_calc_y_offset, 3);
165 Flag::pure_calc_y_offset (SCM smob,
169 return internal_calc_y_offset (smob, true);
172 MAKE_SCHEME_CALLBACK (Flag, calc_y_offset, 1);
174 Flag::calc_y_offset (SCM smob)
176 return internal_calc_y_offset (smob, false);
180 Flag::internal_calc_y_offset (SCM smob, bool pure)
182 Grob *me = unsmob_grob (smob);
183 Grob *stem = me->get_parent (X_AXIS);
184 Direction d = get_grob_direction (stem);
187 = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
189 Interval stem_extent = pure
190 ? stem->pure_height (stem, 0, INT_MAX)
191 : stem->extent (stem, Y_AXIS);
193 return scm_from_double (stem_extent.is_empty ()
195 : stem_extent[d] - d * blot / 2);
198 MAKE_SCHEME_CALLBACK (Flag, calc_x_offset, 1);
200 Flag::calc_x_offset (SCM smob)
202 Grob *me = unsmob_grob (smob);
203 Grob *stem = me->get_parent (X_AXIS);
204 return scm_from_double (stem->extent (stem, X_AXIS)[RIGHT]);
208 "A flag that gets attached to a stem."
209 "The style property is symbol determining"
210 " what style of flag glyph is typeset on a"
211 " @code{Stem}. Valid options include @code{'()}"
212 " for standard flags, @code{'mensural} and"
213 " @code{'no-flag}, which switches off the flag.",