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