]> git.donarmstrong.com Git - lilypond.git/blob - lily/modified-font-metric.cc
*** empty log message ***
[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--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include <cctype>
9
10 #include "modified-font-metric.hh"
11 #include "pango-font.hh"
12 #include "text-metrics.hh"
13 #include "warn.hh"
14 #include "stencil.hh"
15 #include "lookup.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_make_real (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
46 Box 
47 Modified_font_metric::get_indexed_char (int 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 (int i) const
56 {
57   Box b = orig_->get_ascii_char (i);
58   b.scale (magnification_);
59   return b;  
60 }
61
62 int
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 (int k) const
77 {
78   Offset o = orig_->get_indexed_wxwy (k);
79   return o * magnification_;
80 }
81
82 int
83 Modified_font_metric::name_to_index (String s) const
84 {
85   return orig_->name_to_index (s);
86 }
87
88 unsigned
89 Modified_font_metric::index_to_charcode (int i) const
90 {
91   return orig_->index_to_charcode (i);
92 }
93
94 int
95 Modified_font_metric::index_to_ascii (int 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 (int 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 +1 < text.length ())
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 = scm_makfrom0str (text.to_str0 ());
183   Box b = lookup_tex_text_dimension (orig_, stext);
184   if (!b[Y_AXIS].is_empty ())
185     {
186       b.scale (magnification_); 
187       return b;
188     }
189
190   if (output_backend_global == "tex")
191     {
192       b = tex_kludge (text);
193       return b;
194     }
195
196   Interval ydims;
197
198   Real w = 0.0;
199
200   for (int i = 0; i < text.length (); i++) 
201     {
202       Box b = get_ascii_char ((unsigned char)text[i]);
203     
204       w += b[X_AXIS].length ();
205       ydims.unite (b[Y_AXIS]); 
206     }
207   if (ydims.is_empty ())
208     ydims = Interval (0, 0);
209
210   b = Box(Interval(0,w), ydims);
211   return b;
212 }
213
214 Font_metric*
215 Modified_font_metric::original_font () const
216 {
217   return orig_;
218 }
219
220 SCM
221 Modified_font_metric::sub_fonts () const
222 {
223   return orig_->sub_fonts();
224 }
225   
226 String
227 Modified_font_metric::font_name () const
228 {
229   return original_font ()->font_name();
230 }