]> git.donarmstrong.com Git - lilypond.git/blob - lily/modified-font-metric.cc
* buildscripts/gen-bigcheese-scripts.py (i): load .subfonts table.
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "modified-font-metric.hh"
10
11 #include <cctype>
12
13 #include "warn.hh"
14 #include "stencil.hh"
15
16 Modified_font_metric::Modified_font_metric (Font_metric *fm,
17                                             Real magnification,
18                                             String font_encoding,
19                                             String input_encoding)
20 {
21   input_encoding_ = input_encoding;
22   coding_vector_ = SCM_EOL;
23   coding_mapping_ = SCM_EOL;
24   coding_table_ = SCM_EOL;
25   coding_description_ = SCM_EOL;
26   magnification_ = magnification;
27   
28   SCM desc = fm->description_;
29
30   Real total_mag = magnification * scm_to_double (scm_cdr (desc));
31   assert (total_mag);
32   
33   description_ = scm_cons (scm_car (desc), scm_make_real (total_mag));
34   orig_ = fm;
35
36   String metric_coding = orig_->coding_scheme ();
37   if (metric_coding != "FontSpecific"
38       && metric_coding != font_encoding)
39     warning (_f ("conflicting metric coding (%s) and font_encoding (%s)",
40                  metric_coding, font_encoding));
41
42   if (input_encoding_ != "" 
43       && input_encoding_ != "TeX"
44       && input_encoding_ != "ASCII"
45       && input_encoding_ !=  font_encoding)
46     {
47       coding_vector_ = scm_call_1 (ly_scheme_function ("get-coding-vector"),
48                                    scm_makfrom0str (font_encoding.to_str0 ()));
49
50       if (!ly_c_vector_p (coding_vector_))
51         {
52           programming_error ("get-coding-vector  should return vector");
53           coding_vector_ = scm_c_make_vector (256, ly_symbol2scm (".notdef"));
54         }
55
56       coding_table_ = scm_call_1 (ly_scheme_function ("get-coding-table"),
57                                   scm_makfrom0str (font_encoding.to_str0 ()));
58
59       coding_mapping_
60         = scm_call_2 (ly_scheme_function ("make-encoding-mapping"),
61                       coding_vector_,
62                       coding_table_);
63
64       coding_description_ = SCM_EOL;
65       coding_description_
66         = scm_acons (ly_symbol2scm ("input-name"),
67                      scm_makfrom0str (input_encoding_.to_str0 ()),
68                      coding_description_);
69       coding_description_
70         = scm_acons (ly_symbol2scm ("input-vector"),
71                      coding_vector_, coding_description_);
72       coding_description_
73         = scm_acons (ly_symbol2scm ("output-name"),
74                      scm_makfrom0str (orig_->coding_scheme ().to_str0 ()),
75                      coding_description_);
76       coding_description_
77         = scm_acons (ly_symbol2scm ("output-table"),
78                      coding_table_,
79                      coding_description_);
80       coding_description_
81         = scm_acons (ly_symbol2scm ("char-mapping"),
82                      coding_mapping_,
83                      coding_description_);
84     } 
85 }
86
87 SCM
88 Modified_font_metric::make_scaled_font_metric (Font_metric *fm, Real scaling,
89                                                SCM font_encoding,
90                                                SCM input_encoding)
91 {
92   /*
93     UGH.
94    */
95   if (scm_is_symbol (input_encoding))
96     input_encoding = scm_symbol_to_string (input_encoding);
97   
98   String font_encoding_str = ly_symbol2string (font_encoding);
99   String input_encoding_str
100     = scm_is_string (input_encoding) ? ly_scm2string (input_encoding) : ""; 
101   
102   Modified_font_metric *sfm = new Modified_font_metric (fm, scaling,
103                                                         font_encoding_str,
104                                                         input_encoding_str);
105   return sfm->self_scm ();
106 }
107
108 Real
109 Modified_font_metric::design_size () const
110 {
111   return orig_->design_size ();
112 }
113
114
115 Box 
116 Modified_font_metric::get_indexed_char (int i) const
117 {
118   Box b = orig_->get_indexed_char (i);
119   b.scale (magnification_);
120   return b;  
121 }
122
123 Box 
124 Modified_font_metric::get_ascii_char (int i) const
125 {
126   Box b = orig_->get_ascii_char (i);
127   b.scale (magnification_);
128   return b;  
129 }
130
131 int
132 Modified_font_metric::count () const
133 {
134   return orig_->count ();
135 }
136
137 Offset
138 Modified_font_metric::attachment_point (String s) const
139 {
140   Offset o = orig_->attachment_point (s);
141   return o * magnification_;
142 }
143
144 Offset
145 Modified_font_metric::get_indexed_wxwy (int k) const
146 {
147   Offset o = orig_->get_indexed_wxwy (k);
148   return o * magnification_;
149 }
150
151 int
152 Modified_font_metric::name_to_index (String s) const
153 {
154   return orig_->name_to_index (s);
155 }
156
157 unsigned
158 Modified_font_metric::index_to_charcode (int i) const
159 {
160   return orig_->index_to_charcode (i);
161 }
162
163 int
164 Modified_font_metric::index_to_ascii (int k) const
165 {
166   return orig_->index_to_ascii (k);
167 }
168
169 String
170 Modified_font_metric::coding_scheme () const
171 {
172   return input_encoding_;
173 }
174
175 void
176 Modified_font_metric::derived_mark () const
177 {
178   scm_gc_mark (coding_vector_);
179   scm_gc_mark (coding_description_);
180   scm_gc_mark (coding_table_);
181   scm_gc_mark (coding_mapping_);
182 }
183
184 /* TODO: put this klutchness behind ly:option switch.  */  
185 Box
186 Modified_font_metric::tex_kludge (String text) const
187 {
188   Interval ydims;
189   Real w = 0;
190   for (int i = 0; i < text.length (); i++) 
191     {
192       switch (text[i]) 
193         {
194         case '\\':
195           /* Accent marks use width of base letter */
196          if (i +1 < text.length ())
197            {
198              if (text[i+1]=='\'' || text[i+1]=='`' || text[i+1]=='"'
199                  || text[i+1]=='^')
200                {
201                  i++;
202                  break;
203                }
204              /* For string width \\ is a \ and \_ is a _. */
205              if (text[i+1]=='\\' || text[i+1]=='_')        
206                  break;
207            }
208           
209           for (i++; (i < text.length ()) && !isspace (text[i]) 
210                  && text[i]!='{' && text[i]!='}'; i++)
211             ;
212           
213           /* Compensate for the auto-increment in the outer loop. */
214           i--;
215           break;
216
217         case '{':  // Skip '{' and '}'
218         case '}':
219           break;
220         
221         default: 
222           Box b = get_ascii_char ((unsigned char)text[i]);
223           
224           /* Use the width of 'x' for unknown characters */
225           if (b[X_AXIS].length () == 0) 
226             b = get_ascii_char ((unsigned char)'x');
227           
228           w += b[X_AXIS].length ();
229           ydims.unite (b[Y_AXIS]);
230           break;
231         }
232     }
233   
234   if (ydims.is_empty ())
235     ydims = Interval (0, 0);
236   
237   return Box (Interval (0, w), ydims);
238 }
239
240 Box
241 Modified_font_metric::text_dimension (String text) 
242 {
243   Box b; 
244   if (input_encoding_ == "TeX")
245     b = tex_kludge (text);
246   else if (input_encoding_ == "ASCII"
247            || input_encoding_ == "" 
248            || input_encoding_ ==  orig_->coding_scheme ())
249     {
250       Interval ydims;
251
252       Real w = 0.0;
253
254       for (int i = 0; i < text.length (); i++) 
255         {
256           Box b = get_ascii_char ((unsigned char)text[i]);
257     
258           w += b[X_AXIS].length ();
259           ydims.unite (b[Y_AXIS]); 
260         }
261       if (ydims.is_empty ())
262         ydims = Interval (0, 0);
263
264       b = Box(Interval(0,w), ydims);
265     }
266   else
267     {
268       Interval ydims;
269       Real w = 0.0;
270
271       for (int i = 0; i < text.length (); i++) 
272         {
273           SCM sym = scm_vector_ref (coding_vector_,
274                                     scm_from_int((unsigned char) text[i]));
275
276           Box char_box;
277
278           if (!scm_is_symbol (sym))
279             continue;
280
281           char const *chars = scm_i_string_chars (scm_symbol_to_string (sym));
282           
283           int idx = orig_->name_to_index (chars);
284           if (idx >= 0)
285             char_box = orig_->get_indexed_char (idx);
286           
287           char_box.scale (magnification_);
288           if (!char_box[X_AXIS].is_empty ())
289             /* length ? */
290             w += char_box[X_AXIS][RIGHT];
291
292           ydims.unite (char_box[Y_AXIS]);
293         }
294
295       if (ydims.is_empty ())
296         ydims = Interval (0, 0);
297
298       b = Box (Interval (0, w), ydims);
299     }
300   
301   return b;
302 }
303
304 Font_metric*
305 Modified_font_metric::original_font () const
306 {
307   return orig_;
308 }
309
310
311 LY_DEFINE (ly_font_encoding_alist, "ly:font-encoding-alist",
312            1, 0, 0,
313            (SCM font),
314            "Given the Modified_font_metric @var{font}, return an "
315            "alist.  Keys are input-name, input-vector, "
316            "output-name, output-table, mapping.")
317 {
318   Modified_font_metric *fm
319     = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
320   
321   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
322   return fm->coding_description_;
323 }
324
325 LY_DEFINE (ly_font_encoding, "ly:font-encoding",
326            1, 0, 0,
327            (SCM font),
328            "Return encoding of @var{font}.")
329 {
330   Modified_font_metric *fm
331     = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
332   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
333   return ly_symbol2scm (fm->original_font ()->coding_scheme ().to_str0 ());
334 }
335
336 SCM
337 Modified_font_metric::sub_fonts () const
338 {
339   return orig_->sub_fonts();
340 }
341