]> git.donarmstrong.com Git - lilypond.git/blob - lily/modified-font-metric.cc
Merge with master
[lilypond.git] / lily / modified-font-metric.cc
1 /*
2   modified-font-metric.cc -- declare Modified_font_metric
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8 #include <cctype>
9 using namespace std;
10
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
18 Modified_font_metric::Modified_font_metric (Font_metric *fm,
19                                             Real magnification)
20 {
21   magnification_ = magnification;
22
23   SCM desc = fm->description_;
24
25   Real total_mag = magnification * scm_to_double (scm_cdr (desc));
26   assert (total_mag);
27
28   description_ = scm_cons (scm_car (desc), scm_from_double (total_mag));
29   orig_ = fm;
30 }
31
32 SCM
33 Modified_font_metric::make_scaled_font_metric (Font_metric *fm, Real scaling)
34 {
35   Modified_font_metric *sfm = new Modified_font_metric (fm, scaling);
36   return sfm->self_scm ();
37 }
38
39 Real
40 Modified_font_metric::design_size () const
41 {
42   return orig_->design_size ();
43 }
44
45 Box
46 Modified_font_metric::get_indexed_char (vsize i) const
47 {
48   Box b = orig_->get_indexed_char (i);
49   b.scale (magnification_);
50   return b;
51 }
52
53 Box
54 Modified_font_metric::get_ascii_char (vsize i) const
55 {
56   Box b = orig_->get_ascii_char (i);
57   b.scale (magnification_);
58   return b;
59 }
60
61 vsize
62 Modified_font_metric::count () const
63 {
64   return orig_->count ();
65 }
66
67 Offset
68 Modified_font_metric::attachment_point (string s) const
69 {
70   Offset o = orig_->attachment_point (s);
71   return o * magnification_;
72 }
73
74 Offset
75 Modified_font_metric::get_indexed_wxwy (vsize k) const
76 {
77   Offset o = orig_->get_indexed_wxwy (k);
78   return o * magnification_;
79 }
80
81 vsize
82 Modified_font_metric::name_to_index (string s) const
83 {
84   return orig_->name_to_index (s);
85 }
86
87 vsize
88 Modified_font_metric::index_to_charcode (vsize i) const
89 {
90   return orig_->index_to_charcode (i);
91 }
92
93 vsize
94 Modified_font_metric::index_to_ascii (vsize k) const
95 {
96   return orig_->index_to_ascii (k);
97 }
98
99 void
100 Modified_font_metric::derived_mark () const
101 {
102 }
103
104 /* TODO: put this klutchness behind ly:option switch.  */
105 Box
106 Modified_font_metric::tex_kludge (string text) const
107 {
108   Interval ydims;
109   Real w = 0;
110   for (ssize i = 0; i < text.length (); i++)
111     {
112       switch (text[i])
113         {
114         case '\\':
115           /* Accent marks use width of base letter */
116           if (i < text.length () - 1)
117             {
118               if (text[i + 1]=='\'' || text[i + 1]=='`' || text[i + 1]=='"'
119                   || text[i + 1]=='^')
120                 {
121                   i++;
122                   break;
123                 }
124               /* For string width \\ is a \ and \_ is a _. */
125               if (text[i + 1]=='\\' || text[i + 1]=='_')
126                 break;
127             }
128
129           for (i++; (i < text.length ()) && !isspace (text[i])
130                  && text[i]!='{' && text[i]!='}'; i++)
131             ;
132
133           /* Compensate for the auto-increment in the outer loop. */
134           i--;
135           break;
136
137         case '{': // Skip '{' and '}'
138         case '}':
139           break;
140
141         default:
142           Box b = get_ascii_char ((unsigned char)text[i]);
143
144           /* Use the width of 'x' for unknown characters */
145           if (b[X_AXIS].length () == 0)
146             b = get_ascii_char ((unsigned char)'x');
147
148           w += b[X_AXIS].length ();
149           ydims.unite (b[Y_AXIS]);
150           break;
151         }
152     }
153
154   if (ydims.is_empty ())
155     ydims = Interval (0, 0);
156
157   return Box (Interval (0, w), ydims);
158 }
159
160 Stencil
161 Modified_font_metric::text_stencil (string text) const
162 {
163   Box b;
164   if (Pango_font *pf = dynamic_cast<Pango_font *> (orig_))
165     {
166       Stencil stc = pf->text_stencil (text);
167
168       Box b = stc.extent_box ();
169
170       b.scale (magnification_);
171       Stencil scaled (b, stc.expr ());
172       return scaled;
173     }
174
175   return Font_metric::text_stencil (text);
176 }
177
178 Box
179 Modified_font_metric::text_dimension (string text) const
180 {
181   SCM stext = ly_string2scm (text);
182   
183   Box b;
184   if (output_backend_global == "tex")
185     {
186       b = lookup_tex_text_dimension (orig_, stext);
187
188       if (!b[Y_AXIS].is_empty ())
189         {
190           b.scale (magnification_);
191           return b;
192         }
193
194       b = tex_kludge (text);
195       return b;
196     }
197
198   Interval ydims;
199
200   Real w = 0.0;
201
202   for (ssize i = 0; i < text.length (); i++)
203     {
204       Box b = get_ascii_char ((unsigned char)text[i]);
205
206       w += b[X_AXIS].length ();
207       ydims.unite (b[Y_AXIS]);
208     }
209   if (ydims.is_empty ())
210     ydims = Interval (0, 0);
211
212   b = Box (Interval (0, w), ydims);
213   return b;
214 }
215
216 Font_metric *
217 Modified_font_metric::original_font () const
218 {
219   return orig_;
220 }
221
222 SCM
223 Modified_font_metric::sub_fonts () const
224 {
225   return orig_->sub_fonts ();
226 }
227
228 string
229 Modified_font_metric::font_name () const
230 {
231   return original_font ()->font_name ();
232 }