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