]> git.donarmstrong.com Git - lilypond.git/blob - lily/scaled-font-metric.cc
* lily/scaled-font-metric.cc (derived_mark): is a const method.
[lilypond.git] / lily / scaled-font-metric.cc
1 /*
2   scaled-font-metric.cc -- declare Modified_font_metric
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1999--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include <ctype.h>
11
12 #include "warn.hh"
13 #include "scaled-font-metric.hh"
14 #include "string.hh"
15 #include "stencil.hh"
16
17 Modified_font_metric::Modified_font_metric (String coding, Font_metric* m, Real magn)
18 {
19   coding_vector_ = SCM_EOL;
20   coding_permutation_ = SCM_EOL;
21   coding_table_ = SCM_EOL;
22   coding_description_ = SCM_EOL;
23   
24   coding_scheme_ = coding;
25   magnification_ = magn;
26   
27   SCM desc = m->description_;
28
29   Real total_mag = magn * gh_scm2double (ly_cdr (desc));
30   assert (total_mag);
31   
32   description_ = gh_cons (ly_car (desc), gh_double2scm (total_mag));
33   orig_ = m;
34
35   if (coding_scheme_ != "TeX"
36       && coding_scheme_ != "ASCII"
37       && coding_scheme_ !=  orig_->coding_scheme ())
38     {
39       coding_vector_ = scm_call_1 (ly_scheme_function ("get-coding-vector"),
40                                    scm_makfrom0str (coding_scheme_.to_str0 ()));
41
42       if (!gh_vector_p (coding_vector_))
43         {
44           programming_error ("get-coding-vector  should return vector");
45           coding_vector_ = scm_c_make_vector (256, ly_symbol2scm (".notdef"));
46         }
47
48       
49       coding_table_ = scm_call_1 (ly_scheme_function ("get-coding-table"),
50                                   scm_makfrom0str (orig_->coding_scheme ().to_str0 ()));
51           
52       coding_permutation_  = scm_call_2 (ly_scheme_function ("make-encoding-permutation"),
53                                          coding_vector_,
54                                          coding_table_);
55
56       coding_description_= SCM_EOL;
57
58       coding_description_ = scm_acons (ly_symbol2scm ("input-name"),
59                                        scm_makfrom0str (coding_scheme_.to_str0 ()),
60                                        coding_description_);
61
62       coding_description_ = scm_acons (ly_symbol2scm ("input-vector"),
63                                        coding_vector_, coding_description_);
64       coding_description_ = scm_acons (ly_symbol2scm ("output-name"),
65                                        scm_makfrom0str (orig_->coding_scheme ().to_str0 ()),
66                                        coding_description_);
67       coding_description_ = scm_acons (ly_symbol2scm ("output-table"),
68                                        coding_table_,
69                                        coding_description_);
70       
71       coding_description_ = scm_acons (ly_symbol2scm ("coding-permutation"),
72                                        coding_permutation_,
73                                        coding_description_);
74     } 
75 }
76
77
78
79 LY_DEFINE (ly_font_encoding, "ly:font-encoding-alist",
80            1, 0, 0,
81            (SCM font),
82            "Given the Modified_font_metric @var{font}, return an "
83            "alist. Keys are input-name, input-vector, "
84            "output-name, output-table, permutation.")
85 {
86   Modified_font_metric *fm
87     = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
88   
89   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
90   return fm->coding_description_;
91 }
92
93 SCM
94 Modified_font_metric::make_scaled_font_metric (SCM coding, Font_metric *m, Real s)
95 {
96   String scheme = ly_scm2string (coding);
97   
98   Modified_font_metric *sfm = new Modified_font_metric (scheme, m, s);
99   
100   return sfm->self_scm ();
101 }
102
103 Real
104 Modified_font_metric::design_size () const
105 {
106   return orig_->design_size ();
107 }
108
109
110 Box 
111 Modified_font_metric::get_indexed_char (int i) const
112 {
113   Box b = orig_->get_indexed_char (i);
114   b.scale (magnification_);
115   return b;  
116 }
117
118 Box 
119 Modified_font_metric::get_ascii_char (int i) const
120 {
121   Box b = orig_->get_ascii_char (i);
122   b.scale (magnification_);
123   return b;  
124 }
125
126 int
127 Modified_font_metric::count () const
128 {
129   return orig_->count ();
130 }
131
132 Offset
133 Modified_font_metric::get_indexed_wxwy (int k) const
134 {
135   Offset o = orig_->get_indexed_wxwy (k);
136   return o * magnification_;
137 }
138
139 int
140 Modified_font_metric::name_to_index (String s) const
141 {
142   return orig_->name_to_index (s);
143 }
144
145 int
146 Modified_font_metric::index_to_ascii (int k) const
147 {
148   return orig_->index_to_ascii (k);
149 }
150
151 String
152 Modified_font_metric::coding_scheme () const
153 {
154   return coding_scheme_;
155 }
156
157 void
158 Modified_font_metric::derived_mark () const
159 {
160   scm_gc_mark (coding_vector_);
161   scm_gc_mark (coding_description_);
162   scm_gc_mark (coding_table_);
163   scm_gc_mark (coding_permutation_);
164 }
165
166 Box
167 Modified_font_metric::tex_kludge (String text) const
168 {
169   Interval ydims;
170   Real w=0.0;
171
172   /*
173     TODO: put this klutchness behind ly:option switch.
174   */  
175   for (int i = 0; i < text.length (); i++) 
176     {
177       switch (text[i]) 
178         {
179         case '\\':
180           // accent marks use width of base letter
181          if (i +1 < text.length ())
182            {
183              if (text[i+1]=='\'' || text[i+1]=='`' || text[i+1]=='"' ||
184                  text[i+1]=='^')
185                {
186                  i++;
187                  break;
188                }
189              // for string width \\ is a \ and \_ is a _.
190              if (text[i+1]=='\\' || text[i+1]=='_')        
191                {
192                  break;
193                }
194            }
195           
196           for (i++; (i < text.length ()) && !isspace (text[i]) 
197                  && text[i]!='{' && text[i]!='}'; i++)
198             ;
199           
200           // ugh.
201           i--; // Compensate for the increment in the outer loop!
202           break;
203         case '{':  // Skip '{' and '}'
204         case '}':
205           break;
206         
207         default: 
208           Box b = get_ascii_char ((unsigned char)text[i]);
209           
210           // Ugh, use the width of 'x' for unknown characters
211           if (b[X_AXIS].length () == 0) 
212             b = get_ascii_char ((unsigned char)'x');
213           
214           w += b[X_AXIS].length ();
215           ydims.unite (b[Y_AXIS]);
216           break;
217         }
218     }
219   
220   if (ydims.is_empty ())
221     ydims = Interval (0, 0);
222   
223   return Box (Interval (0, w), ydims);
224 }
225
226 Box
227 Modified_font_metric::text_dimension (String text) 
228 {
229   Box b; 
230   if (coding_scheme_ == "TeX")
231     {
232       b = tex_kludge (text);
233     }
234   else if (coding_scheme_ == "ASCII"
235            || coding_scheme_ ==  orig_->coding_scheme ())
236     {
237       Interval ydims;
238
239       Real w=0.0;
240
241       for (int i = 0; i < text.length (); i++) 
242         {
243           Box b = get_ascii_char ((unsigned char)text[i]);
244     
245           w += b[X_AXIS].length ();
246           ydims.unite (b[Y_AXIS]); 
247         }
248       if (ydims.is_empty ())
249         ydims = Interval (0, 0);
250
251       b = Box(Interval(0,w), ydims);
252     }
253   else
254     {
255       Interval ydims;
256       Real w = 0.0;
257
258       for (int i = 0; i < text.length (); i++) 
259         {
260           SCM sym = scm_vector_ref (coding_vector_,
261                                     SCM_MAKINUM((unsigned char) text[i]));
262
263           Box char_box;
264
265           if (!gh_symbol_p (sym))
266             continue;
267
268           char const * chars =  SCM_SYMBOL_CHARS(sym);
269           
270           int idx = orig_->name_to_index (chars);
271           if (idx >= 0)
272             {
273               char_box = orig_->get_indexed_char (idx);
274             }
275           
276           if (!char_box[X_AXIS].is_empty ())
277             w += char_box[X_AXIS][RIGHT]; // length ?
278
279           ydims.unite (char_box[Y_AXIS]);
280         }
281
282       if (ydims.is_empty ())
283         ydims = Interval (0, 0);
284
285           
286       b = Box (Interval (0, w), ydims);
287     }
288   
289   b.scale (magnification_);
290   return b;
291 }