Update from Andrew: tweaks for cross-staff chords snippet.
[lilypond.git] / lily / modified-font-metric.cc
blobad43d756bc38f4dd74846abc50707dbcdb293f9d
1 /*
2 modified-font-metric.cc -- declare Modified_font_metric
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8 #include <cctype>
9 using namespace std;
11 #include "modified-font-metric.hh"
12 #include "pango-font.hh"
13 #include "text-metrics.hh"
14 #include "warn.hh"
15 #include "stencil.hh"
16 #include "main.hh"
17 #include "program-option.hh"
19 Modified_font_metric::Modified_font_metric (Font_metric *fm,
20 Real magnification)
22 magnification_ = magnification;
24 SCM desc = fm->description_;
26 Real total_mag = magnification * scm_to_double (scm_cdr (desc));
27 assert (total_mag);
29 description_ = scm_cons (scm_car (desc), scm_from_double (total_mag));
30 orig_ = fm;
33 SCM
34 Modified_font_metric::make_scaled_font_metric (Font_metric *fm, Real scaling)
36 Modified_font_metric *sfm = new Modified_font_metric (fm, scaling);
37 return sfm->self_scm ();
40 Real
41 Modified_font_metric::design_size () const
43 return orig_->design_size ();
46 Box
47 Modified_font_metric::get_indexed_char (vsize i) const
49 Box b = orig_->get_indexed_char (i);
50 b.scale (magnification_);
51 return b;
54 Box
55 Modified_font_metric::get_ascii_char (vsize i) const
57 Box b = orig_->get_ascii_char (i);
58 b.scale (magnification_);
59 return b;
62 vsize
63 Modified_font_metric::count () const
65 return orig_->count ();
68 Offset
69 Modified_font_metric::attachment_point (string s) const
71 Offset o = orig_->attachment_point (s);
72 return o * magnification_;
75 Offset
76 Modified_font_metric::get_indexed_wxwy (vsize k) const
78 Offset o = orig_->get_indexed_wxwy (k);
79 return o * magnification_;
82 vsize
83 Modified_font_metric::name_to_index (string s) const
85 return orig_->name_to_index (s);
88 vsize
89 Modified_font_metric::index_to_charcode (vsize i) const
91 return orig_->index_to_charcode (i);
94 vsize
95 Modified_font_metric::index_to_ascii (vsize k) const
97 return orig_->index_to_ascii (k);
100 void
101 Modified_font_metric::derived_mark () const
105 /* TODO: put this klutchness behind ly:option switch. */
107 Modified_font_metric::tex_kludge (string text) const
109 Interval ydims;
110 Real w = 0;
111 for (ssize i = 0; i < text.length (); i++)
113 switch (text[i])
115 case '\\':
116 /* Accent marks use width of base letter */
117 if (i < text.length () - 1)
119 if (text[i + 1]=='\'' || text[i + 1]=='`' || text[i + 1]=='"'
120 || text[i + 1]=='^')
122 i++;
123 break;
125 /* For string width \\ is a \ and \_ is a _. */
126 if (text[i + 1]=='\\' || text[i + 1]=='_')
127 break;
130 for (i++; (i < text.length ()) && !isspace (text[i])
131 && text[i]!='{' && text[i]!='}'; i++)
134 /* Compensate for the auto-increment in the outer loop. */
135 i--;
136 break;
138 case '{': // Skip '{' and '}'
139 case '}':
140 break;
142 default:
143 Box b = get_ascii_char ((unsigned char)text[i]);
145 /* Use the width of 'x' for unknown characters */
146 if (b[X_AXIS].length () == 0)
147 b = get_ascii_char ((unsigned char)'x');
149 w += b[X_AXIS].length ();
150 ydims.unite (b[Y_AXIS]);
151 break;
155 if (ydims.is_empty ())
156 ydims = Interval (0, 0);
158 return Box (Interval (0, w), ydims);
161 Stencil
162 Modified_font_metric::text_stencil (string text) const
164 Box b;
165 if (Pango_font *pf = dynamic_cast<Pango_font *> (orig_))
167 Stencil stc = pf->text_stencil (text);
169 Box b = stc.extent_box ();
171 b.scale (magnification_);
172 Stencil scaled (b, stc.expr ());
173 return scaled;
176 return Font_metric::text_stencil (text);
180 Modified_font_metric::text_dimension (string text) const
182 SCM stext = ly_string2scm (text);
184 Box b;
185 if (get_output_backend_name () == "tex")
187 b = lookup_tex_text_dimension (orig_, stext);
189 if (!b[Y_AXIS].is_empty ())
191 b.scale (magnification_);
192 return b;
195 b = tex_kludge (text);
196 return b;
199 Interval ydims;
201 Real w = 0.0;
203 for (ssize i = 0; i < text.length (); i++)
205 Box b = get_ascii_char ((unsigned char)text[i]);
207 w += b[X_AXIS].length ();
208 ydims.unite (b[Y_AXIS]);
210 if (ydims.is_empty ())
211 ydims = Interval (0, 0);
213 b = Box (Interval (0, w), ydims);
214 return b;
217 Font_metric *
218 Modified_font_metric::original_font () const
220 return orig_;
224 Modified_font_metric::sub_fonts () const
226 return orig_->sub_fonts ();
229 string
230 Modified_font_metric::font_name () const
232 return original_font ()->font_name ();