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 (width, (SCM));
37 DECLARE_SCHEME_CALLBACK (calc_y_offset, (SCM));
38 DECLARE_SCHEME_CALLBACK (pure_calc_y_offset, (SCM, SCM, SCM));
39 DECLARE_SCHEME_CALLBACK (calc_x_offset, (SCM));
40 DECLARE_GROB_INTERFACE ();
42 static SCM internal_calc_y_offset (SCM smob, bool pure);
45 MAKE_SCHEME_CALLBACK (Flag, width, 1);
47 Flag::width (SCM smob)
49 Grob *me = unsmob_grob (smob);
50 Stencil *sten = unsmob_stencil (me->get_property ("stencil"));
52 return ly_interval2scm (Interval (0.0, 0.0));
54 Grob *stem = me->get_parent (X_AXIS);
58 This reproduces a bad hard-coding that has been in the code for quite some time:
59 the bounding boxes for the flags are slightly off and need to be fixed.
62 return ly_interval2scm (sten->extent (X_AXIS) - stem->extent (stem, X_AXIS)[RIGHT]);
64 MAKE_SCHEME_CALLBACK (Flag, print, 1);
66 Flag::print (SCM smob)
68 Grob *me = unsmob_grob (smob);
69 Grob *stem = me->get_parent (X_AXIS);
71 Direction d = get_grob_direction (stem);
72 int log = Stem::duration_log (stem);
75 SCM flag_style_scm = me->get_property ("style");
76 if (scm_is_symbol (flag_style_scm))
77 flag_style = ly_symbol2string (flag_style_scm);
79 if (flag_style == "no-flag")
80 return Stencil ().smobbed_copy ();
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 Font_metric *fm = Font_interface::get_default_font (me);
111 Stencil flag = fm->find_by_name ("flags." + font_char);
112 if (flag.is_empty ())
113 me->warning (_f ("flag `%s' not found", font_char));
116 TODO: maybe property stroke-style should take different values,
117 e.g. "" (i.e. no stroke), "single" and "double" (currently, it's
119 SCM stroke_style_scm = me->get_property ("stroke-style");
120 if (scm_is_string (stroke_style_scm))
122 string stroke_style = ly_scm2string (stroke_style_scm);
123 if (!stroke_style.empty ())
125 string font_char = flag_style + to_string (dir) + stroke_style;
126 Stencil stroke = fm->find_by_name ("flags." + font_char);
127 if (stroke.is_empty ())
129 font_char = to_string (dir) + stroke_style;
130 stroke = fm->find_by_name ("flags." + font_char);
132 if (stroke.is_empty ())
133 me->warning (_f ("flag stroke `%s' not found", font_char));
135 flag.add_stencil (stroke);
139 return flag.smobbed_copy ();
142 MAKE_SCHEME_CALLBACK (Flag, pure_calc_y_offset, 3);
144 Flag::pure_calc_y_offset (SCM smob,
148 return internal_calc_y_offset (smob, true);
151 MAKE_SCHEME_CALLBACK (Flag, calc_y_offset, 1);
153 Flag::calc_y_offset (SCM smob)
155 return internal_calc_y_offset (smob, false);
159 Flag::internal_calc_y_offset (SCM smob, bool pure)
161 Grob *me = unsmob_grob (smob);
162 Grob *stem = me->get_parent (X_AXIS);
163 Direction d = get_grob_direction (stem);
166 = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
169 ? stem->pure_height (stem, 0, INT_MAX)[d]
170 : stem->extent (stem, Y_AXIS)[d];
172 return scm_from_double (y2 - d * blot / 2);
175 MAKE_SCHEME_CALLBACK (Flag, calc_x_offset, 1);
177 Flag::calc_x_offset (SCM smob)
179 Grob *me = unsmob_grob (smob);
180 Grob *stem = me->get_parent (X_AXIS);
181 return scm_from_double (stem->extent (stem, X_AXIS)[RIGHT]);
185 "A flag that gets attached to a stem."
186 "The style property is symbol determining"
187 " what style of flag glyph is typeset on a"
188 " @code{Stem}. Valid options include @code{'()}"
189 " for standard flags, @code{'mensural} and"
190 " @code{'no-flag}, which switches off the flag.",