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