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