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