]> git.donarmstrong.com Git - lilypond.git/blob - lily/flag.cc
Issue 4550 (1/2) Avoid "using namespace std;" in included files
[lilypond.git] / lily / flag.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1996--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5   Jan Nieuwenhuizen <janneke@gnu.org>
6
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.
11
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.
16
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/>.
19 */
20
21 #include "stem.hh"
22
23 #include "directional-element-interface.hh"
24 #include "font-interface.hh"
25 #include "grob.hh"
26 #include "international.hh"
27 #include "output-def.hh"
28 #include "staff-symbol-referencer.hh"
29 #include "stencil.hh"
30 #include "warn.hh"
31
32 using std::string;
33
34 class Flag
35 {
36 public:
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));
43
44   static SCM internal_calc_y_offset (SCM smob, bool pure);
45 };
46
47 MAKE_SCHEME_CALLBACK (Flag, width, 1);
48 SCM
49 Flag::width (SCM smob)
50 {
51   Grob *me = unsmob<Grob> (smob);
52   Stencil *sten = unsmob<Stencil> (me->get_property ("stencil"));
53   if (!sten)
54     return ly_interval2scm (Interval (0.0, 0.0));
55
56   Grob *stem = me->get_parent (X_AXIS);
57
58   /*
59     TODO:
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.
62   */
63
64   return ly_interval2scm (sten->extent (X_AXIS) - stem->extent (stem, X_AXIS)[RIGHT]);
65 }
66
67 MAKE_SCHEME_CALLBACK (Flag, glyph_name, 1);
68 SCM
69 Flag::glyph_name (SCM smob)
70 {
71   Grob *me = unsmob<Grob> (smob);
72   Grob *stem = me->get_parent (X_AXIS);
73
74   Direction d = get_grob_direction (stem);
75   int log = Stem::duration_log (stem);
76   string flag_style;
77
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);
81
82   bool adjust = true;
83
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
91        touches a staff line.
92     */
93     {
94       if (adjust)
95         {
96           Real ss = Staff_symbol_referencer::staff_space (me);
97           int p = (int) (rint (stem->extent (stem, Y_AXIS)[d] * 2 / ss));
98           staffline_offs
99             = Staff_symbol_referencer::on_line (stem, p) ? "0" : "1";
100         }
101       else
102         staffline_offs = "2";
103     }
104   else
105     staffline_offs = "";
106
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);
111 }
112
113 MAKE_SCHEME_CALLBACK (Flag, print, 1);
114 SCM
115 Flag::print (SCM smob)
116 {
117   Grob *me = unsmob<Grob> (smob);
118   Grob *stem = me->get_parent (X_AXIS);
119
120   Direction d = get_grob_direction (stem);
121   string flag_style;
122
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);
126
127   if (flag_style == "no-flag")
128     return Stencil ().smobbed_copy ();
129
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));
136
137   /*
138     TODO: maybe property stroke-style should take different values,
139     e.g. "" (i.e. no stroke), "single" and "double" (currently, it's
140     '() or "grace").  */
141   SCM stroke_style_scm = me->get_property ("stroke-style");
142   if (scm_is_string (stroke_style_scm))
143     {
144       string stroke_style = ly_scm2string (stroke_style_scm);
145       if (!stroke_style.empty ())
146         {
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 ())
150             {
151               font_char = ::to_string (dir) + stroke_style;
152               stroke = fm->find_by_name ("flags." + font_char);
153             }
154           if (stroke.is_empty ())
155             me->warning (_f ("flag stroke `%s' not found", font_char));
156           else
157             flag.add_stencil (stroke);
158         }
159     }
160
161   return flag.smobbed_copy ();
162 }
163
164 MAKE_SCHEME_CALLBACK (Flag, pure_calc_y_offset, 3);
165 SCM
166 Flag::pure_calc_y_offset (SCM smob,
167                           SCM /* beg */,
168                           SCM /* end */)
169 {
170   return internal_calc_y_offset (smob, true);
171 }
172
173 MAKE_SCHEME_CALLBACK (Flag, calc_y_offset, 1);
174 SCM
175 Flag::calc_y_offset (SCM smob)
176 {
177   return internal_calc_y_offset (smob, false);
178 }
179
180 SCM
181 Flag::internal_calc_y_offset (SCM smob, bool pure)
182 {
183   Grob *me = unsmob<Grob> (smob);
184   Grob *stem = me->get_parent (X_AXIS);
185   Direction d = get_grob_direction (stem);
186
187   Real blot
188     = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
189
190   Interval stem_extent = pure
191                          ? stem->pure_y_extent (stem, 0, INT_MAX)
192                          : stem->extent (stem, Y_AXIS);
193
194   return scm_from_double (stem_extent.is_empty ()
195                           ? 0.0
196                           : stem_extent[d] - d * blot / 2);
197 }
198
199 MAKE_SCHEME_CALLBACK (Flag, calc_x_offset, 1);
200 SCM
201 Flag::calc_x_offset (SCM smob)
202 {
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]);
206 }
207
208 ADD_INTERFACE (Flag,
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.",
215
216                /* properties */
217                "glyph-name "
218                "style "
219                "stroke-style "
220               );