2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1996--2015 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"
37 DECLARE_SCHEME_CALLBACK (print, (SCM));
38 DECLARE_SCHEME_CALLBACK (glyph_name, (SCM));
39 DECLARE_SCHEME_CALLBACK (width, (SCM));
40 DECLARE_SCHEME_CALLBACK (calc_y_offset, (SCM));
41 DECLARE_SCHEME_CALLBACK (pure_calc_y_offset, (SCM, SCM, SCM));
42 DECLARE_SCHEME_CALLBACK (calc_x_offset, (SCM));
44 static SCM internal_calc_y_offset (SCM smob, bool pure);
47 MAKE_SCHEME_CALLBACK (Flag, width, 1);
49 Flag::width (SCM smob)
51 Grob *me = unsmob<Grob> (smob);
52 Stencil *sten = unsmob<Stencil> (me->get_property ("stencil"));
54 return ly_interval2scm (Interval (0.0, 0.0));
56 Grob *stem = me->get_parent (X_AXIS);
60 This reproduces a bad hard-coding that has been in the code for quite some time:
61 the bounding boxes for the flags are slightly off and need to be fixed.
64 return ly_interval2scm (sten->extent (X_AXIS) - stem->extent (stem, X_AXIS)[RIGHT]);
67 MAKE_SCHEME_CALLBACK (Flag, glyph_name, 1);
69 Flag::glyph_name (SCM smob)
71 Grob *me = unsmob<Grob> (smob);
72 Grob *stem = me->get_parent (X_AXIS);
74 Direction d = get_grob_direction (stem);
75 int log = Stem::duration_log (stem);
78 SCM flag_style_scm = me->get_property ("style");
79 if (scm_is_symbol (flag_style_scm))
80 flag_style = ly_symbol2string (flag_style_scm);
84 string staffline_offs;
85 if (flag_style == "mensural")
86 /* Mensural notation: For notes on staff lines, use different
87 flags than for notes between staff lines. The idea is that
88 flags are always vertically aligned with the staff lines,
89 regardless if the note head is on a staff line or between two
90 staff lines. In other words, the inner end of a flag always
96 Real ss = Staff_symbol_referencer::staff_space (me);
97 int p = (int) (rint (stem->extent (stem, Y_AXIS)[d] * 2 / ss));
99 = Staff_symbol_referencer::on_line (stem, p) ? "0" : "1";
102 staffline_offs = "2";
107 char dir = (d == UP) ? 'u' : 'd';
108 string font_char = flag_style
109 + ::to_string (dir) + staffline_offs + ::to_string (log);
110 return ly_string2scm ("flags." + font_char);
113 MAKE_SCHEME_CALLBACK (Flag, print, 1);
115 Flag::print (SCM smob)
117 Grob *me = unsmob<Grob> (smob);
118 Grob *stem = me->get_parent (X_AXIS);
120 Direction d = get_grob_direction (stem);
123 SCM flag_style_scm = me->get_property ("style");
124 if (scm_is_symbol (flag_style_scm))
125 flag_style = ly_symbol2string (flag_style_scm);
127 if (flag_style == "no-flag")
128 return Stencil ().smobbed_copy ();
130 char dir = (d == UP) ? 'u' : 'd';
131 Font_metric *fm = Font_interface::get_default_font (me);
132 string font_char = robust_scm2string (me->get_property ("glyph-name"), "");
133 Stencil flag = fm->find_by_name (font_char);
134 if (flag.is_empty ())
135 me->warning (_f ("flag `%s' not found", font_char));
138 TODO: maybe property stroke-style should take different values,
139 e.g. "" (i.e. no stroke), "single" and "double" (currently, it's
141 SCM stroke_style_scm = me->get_property ("stroke-style");
142 if (scm_is_string (stroke_style_scm))
144 string stroke_style = ly_scm2string (stroke_style_scm);
145 if (!stroke_style.empty ())
147 string font_char = flag_style + ::to_string (dir) + stroke_style;
148 Stencil stroke = fm->find_by_name ("flags." + font_char);
149 if (stroke.is_empty ())
151 font_char = ::to_string (dir) + stroke_style;
152 stroke = fm->find_by_name ("flags." + font_char);
154 if (stroke.is_empty ())
155 me->warning (_f ("flag stroke `%s' not found", font_char));
157 flag.add_stencil (stroke);
161 return flag.smobbed_copy ();
164 MAKE_SCHEME_CALLBACK (Flag, pure_calc_y_offset, 3);
166 Flag::pure_calc_y_offset (SCM smob,
170 return internal_calc_y_offset (smob, true);
173 MAKE_SCHEME_CALLBACK (Flag, calc_y_offset, 1);
175 Flag::calc_y_offset (SCM smob)
177 return internal_calc_y_offset (smob, false);
181 Flag::internal_calc_y_offset (SCM smob, bool pure)
183 Grob *me = unsmob<Grob> (smob);
184 Grob *stem = me->get_parent (X_AXIS);
185 Direction d = get_grob_direction (stem);
188 = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
190 Interval stem_extent = pure
191 ? stem->pure_y_extent (stem, 0, INT_MAX)
192 : stem->extent (stem, Y_AXIS);
194 return scm_from_double (stem_extent.is_empty ()
196 : stem_extent[d] - d * blot / 2);
199 MAKE_SCHEME_CALLBACK (Flag, calc_x_offset, 1);
201 Flag::calc_x_offset (SCM smob)
203 Grob *me = unsmob<Grob> (smob);
204 Grob *stem = me->get_parent (X_AXIS);
205 return scm_from_double (stem->extent (stem, X_AXIS)[RIGHT]);
209 "A flag that gets attached to a stem."
210 "The style property is symbol determining"
211 " what style of flag glyph is typeset on a"
212 " @code{Stem}. Valid options include @code{'()}"
213 " for standard flags, @code{'mensural} and"
214 " @code{'no-flag}, which switches off the flag.",