2 modified-font-metric.cc -- declare Modified_font_metric
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
12 #include "modified-font-metric.hh"
16 Modified_font_metric::Modified_font_metric (String input_encoding,
17 Font_metric *m, Real magn)
21 THIS.coding_scheme == input encoding.
22 ORIG.coding_scheme () == font_encoding.
24 encoding is hairy enough by itself, should fix treacherous naming. */
26 coding_scheme_ = input_encoding;
28 coding_vector_ = SCM_EOL;
29 coding_mapping_ = SCM_EOL;
30 coding_table_ = SCM_EOL;
31 coding_description_ = SCM_EOL;
33 magnification_ = magn;
35 SCM desc = m->description_;
37 Real total_mag = magn * scm_to_double (scm_cdr (desc));
40 description_ = scm_cons (scm_car (desc), scm_make_real (total_mag));
43 if (coding_scheme_ != ""
44 && coding_scheme_ != "TeX"
45 && coding_scheme_ != "ASCII"
46 && coding_scheme_ != orig_->coding_scheme ())
49 = scm_call_1 (ly_scheme_function ("get-coding-vector"),
50 scm_makfrom0str (coding_scheme_.to_str0 ()));
52 if (!ly_c_vector_p (coding_vector_))
54 programming_error ("get-coding-vector should return vector");
55 coding_vector_ = scm_c_make_vector (256, ly_symbol2scm (".notdef"));
59 = scm_call_1 (ly_scheme_function ("get-coding-table"),
60 scm_makfrom0str (orig_->coding_scheme ().to_str0 ()));
63 = scm_call_2 (ly_scheme_function ("make-encoding-mapping"),
67 coding_description_ = SCM_EOL;
69 = scm_acons (ly_symbol2scm ("input-name"),
70 scm_makfrom0str (coding_scheme_.to_str0 ()),
73 = scm_acons (ly_symbol2scm ("input-vector"),
74 coding_vector_, coding_description_);
76 = scm_acons (ly_symbol2scm ("output-name"),
77 scm_makfrom0str (orig_->coding_scheme ().to_str0 ()),
80 = scm_acons (ly_symbol2scm ("output-table"),
84 = scm_acons (ly_symbol2scm ("char-mapping"),
90 Modified_font_metric::make_scaled_font_metric (SCM coding,
91 Font_metric *m, Real s)
96 if (scm_is_symbol (coding))
97 coding = scm_symbol_to_string (coding);
99 String scheme = scm_is_string (coding) ? ly_scm2string (coding) : "";
101 Modified_font_metric *sfm = new Modified_font_metric (scheme, m, s);
103 return sfm->self_scm ();
107 Modified_font_metric::design_size () const
109 return orig_->design_size ();
114 Modified_font_metric::get_indexed_char (int i) const
116 Box b = orig_->get_indexed_char (i);
117 b.scale (magnification_);
122 Modified_font_metric::get_ascii_char (int i) const
124 Box b = orig_->get_ascii_char (i);
125 b.scale (magnification_);
130 Modified_font_metric::count () const
132 return orig_->count ();
136 Modified_font_metric::get_indexed_wxwy (int k) const
138 Offset o = orig_->get_indexed_wxwy (k);
139 return o * magnification_;
143 Modified_font_metric::name_to_index (String s) const
145 return orig_->name_to_index (s);
149 Modified_font_metric::index_to_ascii (int k) const
151 return orig_->index_to_ascii (k);
155 Modified_font_metric::coding_scheme () const
157 return coding_scheme_;
161 Modified_font_metric::derived_mark () const
163 scm_gc_mark (coding_vector_);
164 scm_gc_mark (coding_description_);
165 scm_gc_mark (coding_table_);
166 scm_gc_mark (coding_mapping_);
169 /* TODO: put this klutchness behind ly:option switch. */
171 Modified_font_metric::tex_kludge (String text) const
175 for (int i = 0; i < text.length (); i++)
180 /* Accent marks use width of base letter */
181 if (i +1 < text.length ())
183 if (text[i+1]=='\'' || text[i+1]=='`' || text[i+1]=='"'
189 /* For string width \\ is a \ and \_ is a _. */
190 if (text[i+1]=='\\' || text[i+1]=='_')
194 for (i++; (i < text.length ()) && !isspace (text[i])
195 && text[i]!='{' && text[i]!='}'; i++)
198 /* Compensate for the auto-increment in the outer loop. */
202 case '{': // Skip '{' and '}'
207 Box b = get_ascii_char ((unsigned char)text[i]);
209 /* Use the width of 'x' for unknown characters */
210 if (b[X_AXIS].length () == 0)
211 b = get_ascii_char ((unsigned char)'x');
213 w += b[X_AXIS].length ();
214 ydims.unite (b[Y_AXIS]);
219 if (ydims.is_empty ())
220 ydims = Interval (0, 0);
222 return Box (Interval (0, w), ydims);
226 Modified_font_metric::text_dimension (String text)
229 if (coding_scheme_ == "TeX")
230 b = tex_kludge (text);
231 else if (coding_scheme_ == "ASCII"
232 || coding_scheme_ == ""
233 || coding_scheme_ == orig_->coding_scheme ())
239 for (int i = 0; i < text.length (); i++)
241 Box b = get_ascii_char ((unsigned char)text[i]);
243 w += b[X_AXIS].length ();
244 ydims.unite (b[Y_AXIS]);
246 if (ydims.is_empty ())
247 ydims = Interval (0, 0);
249 b = Box(Interval(0,w), ydims);
256 for (int i = 0; i < text.length (); i++)
258 SCM sym = scm_vector_ref (coding_vector_,
259 scm_from_int((unsigned char) text[i]));
263 if (!scm_is_symbol (sym))
266 char const *chars = scm_i_string_chars (scm_symbol_to_string (sym));
268 int idx = orig_->name_to_index (chars);
270 char_box = orig_->get_indexed_char (idx);
272 char_box.scale (magnification_);
273 if (!char_box[X_AXIS].is_empty ())
275 w += char_box[X_AXIS][RIGHT];
277 ydims.unite (char_box[Y_AXIS]);
280 if (ydims.is_empty ())
281 ydims = Interval (0, 0);
283 b = Box (Interval (0, w), ydims);
290 Modified_font_metric::original_font () const
296 LY_DEFINE (ly_font_encoding_alist, "ly:font-encoding-alist",
299 "Given the Modified_font_metric @var{font}, return an "
300 "alist. Keys are input-name, input-vector, "
301 "output-name, output-table, mapping.")
303 Modified_font_metric *fm
304 = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
306 SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
307 return fm->coding_description_;
310 LY_DEFINE (ly_font_encoding, "ly:font-encoding",
313 "Return encoding of @var{font}.")
315 Modified_font_metric *fm
316 = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
317 SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
318 return ly_symbol2scm (fm->original_font ()->coding_scheme ().to_str0 ());