]> git.donarmstrong.com Git - lilypond.git/blob - lily/font-metric.cc
* scm/output-ps.scm (define-fonts): fix scaling.
[lilypond.git] / lily / font-metric.cc
1 /*   
2   font-metric.cc --  implement 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     Mats Bengtsson <matsb@s3.kth.se> (the ugly TeX parsing in text_dimension)
9  */
10
11 #include <math.h>
12 #include <ctype.h>
13
14 #include "virtual-methods.hh"
15 #include "warn.hh"
16 #include "stencil.hh"
17 #include "ly-smobs.icc"
18 #include "font-metric.hh"
19 #include "string.hh"
20
21 Real
22 Font_metric::design_size () const
23 {
24   return 1.0;
25 }
26
27 Box
28 Font_metric::text_dimension (String text) const
29 {
30   Interval ydims;
31   Real w=0.0;
32   
33   for (int i = 0; i < text.length (); i++) 
34     {
35       
36       switch (text[i]) 
37         {
38         case '\\':
39   // accent marks use width of base letter
40          if (i +1 < text.length ())
41            {
42              if (text[i+1]=='\'' || text[i+1]=='`' || text[i+1]=='"' ||
43                  text[i+1]=='^')
44                {
45                  i++;
46                  break;
47                }
48              // for string width \\ is a \ and \_ is a _.
49              if (text[i+1]=='\\' || text[i+1]=='_')        
50                {
51                  break;
52                }
53            }
54           
55           for (i++; (i < text.length ()) && !isspace (text[i]) 
56                  && text[i]!='{' && text[i]!='}'; i++)
57             ;
58           // ugh.
59           i--; // Compensate for the increment in the outer loop!
60           break;
61         case '{':  // Skip '{' and '}'
62         case '}':
63           break;
64         
65         default: 
66           Box b = get_ascii_char ((unsigned char)text[i]);
67           
68           // Ugh, use the width of 'x' for unknown characters
69           if (b[X_AXIS].length () == 0) 
70             b = get_ascii_char ((unsigned char)'x');
71           
72           w += b[X_AXIS].length ();
73           ydims.unite (b[Y_AXIS]);
74           break;
75         }
76     }
77   if (ydims.is_empty ())
78     ydims = Interval (0,0);
79
80   return Box (Interval (0, w), ydims);
81 }
82
83
84
85 Font_metric::~Font_metric ()
86 {
87 }
88
89 Font_metric::Font_metric ()
90 {
91   description_ = SCM_EOL;
92   self_scm_ = SCM_EOL;
93   smobify_self ();
94 }
95
96 Font_metric::Font_metric (Font_metric const &)
97 {
98 }
99
100 int
101 Font_metric::count () const
102 {
103   return 0;
104 }
105
106 Box 
107 Font_metric::get_ascii_char (int) const
108 {
109   return Box (Interval (0,0),Interval (0,0));
110 }
111
112 Box 
113 Font_metric::get_indexed_char (int k) const
114 {
115   return get_ascii_char (k);
116 }
117
118
119 int
120 Font_metric::name_to_index (String) const
121 {
122   return -1;
123 }
124
125 Offset
126 Font_metric::get_indexed_wxwy (int )const
127 {
128   return Offset (0,0);
129 }
130
131 void
132 Font_metric::derived_mark ()const
133 {
134   
135 }
136
137 SCM
138 Font_metric::mark_smob (SCM s)
139 {
140   Font_metric * m = (Font_metric*) SCM_CELL_WORD_1 (s);
141
142   m->derived_mark ();
143   return m->description_;
144 }
145
146 int
147 Font_metric::print_smob (SCM s, SCM port, scm_print_state *)
148 {
149   Font_metric *m = unsmob_metrics (s);
150   scm_puts ("#<", port);
151   scm_puts (classname (m), port);
152   scm_puts (" ", port);
153   scm_write (m->description_, port);
154   scm_puts (">", port);
155   return 1;
156 }
157
158
159
160 IMPLEMENT_SMOBS (Font_metric);
161 IMPLEMENT_DEFAULT_EQUAL_P (Font_metric);
162 IMPLEMENT_TYPE_P (Font_metric, "ly:font-metric?");
163
164 Stencil
165 Font_metric::find_by_name (String) const
166 {
167   Stencil m ;
168   return m;
169 }
170
171 LY_DEFINE (ly_find_glyph_by_name, "ly:find-glyph-by-name", 2 , 0, 0,
172           (SCM font, SCM name),
173           "This function retrieves a Stencil for the glyph named @var{name} "
174            "in "
175            "@var{font}.  "
176            "The font must be available as an AFM file. If the glyph "
177            "is not found, @code{#f} is returned. ")
178 {
179   Font_metric *fm = unsmob_metrics (font);
180   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "font-metric");
181   SCM_ASSERT_TYPE (gh_string_p (name), name, SCM_ARG2, __FUNCTION__, "string");
182
183   Stencil m =  fm->find_by_name (ly_scm2string (name));
184
185   /*
186     TODO: make optional argument for default if not found.
187    */
188   return m.smobbed_copy ();
189 }
190
191 LY_DEFINE (ly_get_glyph, "ly:get-glyph", 2 , 0, 0,
192           (SCM font, SCM index),
193           "This function retrieves a Stencil for the glyph numbered @var{index} in "
194 "@var{font}. ")
195 {
196   Font_metric *fm = unsmob_metrics (font);
197   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "font-metric");
198   SCM_ASSERT_TYPE (gh_number_p (index), index, SCM_ARG2, __FUNCTION__, "number");
199
200   return fm->get_ascii_char_stencil (gh_scm2int (index)).smobbed_copy ();
201 }
202
203 LY_DEFINE (ly_text_dimension,"ly:text-dimension", 2 , 0, 0,
204           (SCM font, SCM text),
205           "Given the font metric in @var{font} and the string @var{text}, compute "
206 "the extents of that text in that font. The return value is a pair of "
207 "number-pairs.")
208 {
209   Box b;
210   Font_metric *fm = unsmob_metrics (font);
211   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "font-metric");
212   SCM_ASSERT_TYPE (gh_string_p (text), text, SCM_ARG2, __FUNCTION__, "string");
213
214   b = fm->text_dimension (ly_scm2string (text));
215   
216   return gh_cons (ly_interval2scm (b[X_AXIS]), ly_interval2scm (b[Y_AXIS]));
217 }
218
219 LY_DEFINE (ly_font_name,"ly:font-name", 1 , 0, 0,
220           (SCM font),
221            "Given the font metric @var{font}, return the corresponding file name. ")
222 {
223   Font_metric *fm = unsmob_metrics (font);
224   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "font-metric");
225   return gh_car (fm->description_);
226 }
227
228 LY_DEFINE (ly_font_magnification,"ly:font-magnification", 1 , 0, 0,
229           (SCM font),
230            "Given the font metric @var{font}, return the "
231            "magnification, relative to the current outputscale.")
232 {
233   Font_metric *fm = unsmob_metrics (font);
234   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "font-metric");
235   return gh_cdr (fm->description_);
236 }
237
238 LY_DEFINE (ly_font_design_size,"ly:font-design-size", 1 , 0, 0,
239           (SCM font),
240            "Given the font metric @var{font}, return the "
241            "design size, relative to the current outputscale.")
242 {
243   Font_metric *fm = unsmob_metrics (font);
244   SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "font-metric");
245   return gh_double2scm  (fm->design_size ());
246 }
247
248
249 Stencil
250 Font_metric::get_ascii_char_stencil (int code)  const
251 {
252   SCM at = scm_list_n (ly_symbol2scm ("char"), gh_int2scm (code),
253                        SCM_UNDEFINED);
254   at = fontify_atom (this, at);
255   Box b = get_ascii_char (code);
256   return Stencil (b, at);
257 }
258
259 Stencil
260 Font_metric::get_indexed_char_stencil (int code)  const
261 {
262   SCM at = scm_list_n (ly_symbol2scm ("char"), gh_int2scm (code),
263                        SCM_UNDEFINED);
264   at = fontify_atom (this, at);
265   Box b = get_indexed_char (code);
266   return Stencil (b, at);
267 }