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>
9 #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 ())
48 /* FIXME: this is broken, cannot get font encoding from font/AFM file,
49 should use encoding from font-tree in fonts.scm. */
52 = scm_call_1 (ly_scheme_function ("get-coding-vector"),
53 scm_makfrom0str (coding_scheme_.to_str0 ()));
55 if (!ly_c_vector_p (coding_vector_))
57 programming_error ("get-coding-vector should return vector");
58 coding_vector_ = scm_c_make_vector (256, ly_symbol2scm (".notdef"));
62 = scm_call_1 (ly_scheme_function ("get-coding-table"),
63 scm_makfrom0str (orig_->coding_scheme ().to_str0 ()));
66 = scm_call_2 (ly_scheme_function ("make-encoding-mapping"),
70 coding_description_ = SCM_EOL;
72 = scm_acons (ly_symbol2scm ("input-name"),
73 scm_makfrom0str (coding_scheme_.to_str0 ()),
76 = scm_acons (ly_symbol2scm ("input-vector"),
77 coding_vector_, coding_description_);
79 = scm_acons (ly_symbol2scm ("output-name"),
80 scm_makfrom0str (orig_->coding_scheme ().to_str0 ()),
83 = scm_acons (ly_symbol2scm ("output-table"),
87 = scm_acons (ly_symbol2scm ("char-mapping"),
93 Modified_font_metric::make_scaled_font_metric (SCM coding,
94 Font_metric *m, Real s)
99 if (scm_is_symbol (coding))
100 coding = scm_symbol_to_string (coding);
102 String scheme = scm_is_string (coding) ? ly_scm2string (coding) : "";
104 Modified_font_metric *sfm = new Modified_font_metric (scheme, m, s);
106 return sfm->self_scm ();
110 Modified_font_metric::design_size () const
112 return orig_->design_size ();
117 Modified_font_metric::get_indexed_char (int i) const
119 Box b = orig_->get_indexed_char (i);
120 b.scale (magnification_);
125 Modified_font_metric::get_ascii_char (int i) const
127 Box b = orig_->get_ascii_char (i);
128 b.scale (magnification_);
133 Modified_font_metric::count () const
135 return orig_->count ();
139 Modified_font_metric::get_indexed_wxwy (int k) const
141 Offset o = orig_->get_indexed_wxwy (k);
142 return o * magnification_;
146 Modified_font_metric::name_to_index (String s) const
148 return orig_->name_to_index (s);
152 Modified_font_metric::index_to_ascii (int k) const
154 return orig_->index_to_ascii (k);
158 Modified_font_metric::coding_scheme () const
160 return coding_scheme_;
164 Modified_font_metric::derived_mark () const
166 scm_gc_mark (coding_vector_);
167 scm_gc_mark (coding_description_);
168 scm_gc_mark (coding_table_);
169 scm_gc_mark (coding_mapping_);
172 /* TODO: put this klutchness behind ly:option switch. */
174 Modified_font_metric::tex_kludge (String text) const
178 for (int i = 0; i < text.length (); i++)
183 /* Accent marks use width of base letter */
184 if (i +1 < text.length ())
186 if (text[i+1]=='\'' || text[i+1]=='`' || text[i+1]=='"'
192 /* For string width \\ is a \ and \_ is a _. */
193 if (text[i+1]=='\\' || text[i+1]=='_')
197 for (i++; (i < text.length ()) && !isspace (text[i])
198 && text[i]!='{' && text[i]!='}'; i++)
201 /* Compensate for the auto-increment in the outer loop. */
205 case '{': // Skip '{' and '}'
210 Box b = get_ascii_char ((unsigned char)text[i]);
212 /* Use the width of 'x' for unknown characters */
213 if (b[X_AXIS].length () == 0)
214 b = get_ascii_char ((unsigned char)'x');
216 w += b[X_AXIS].length ();
217 ydims.unite (b[Y_AXIS]);
222 if (ydims.is_empty ())
223 ydims = Interval (0, 0);
225 return Box (Interval (0, w), ydims);
229 Modified_font_metric::text_dimension (String text)
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 ())
242 for (int i = 0; i < text.length (); i++)
244 Box b = get_ascii_char ((unsigned char)text[i]);
246 w += b[X_AXIS].length ();
247 ydims.unite (b[Y_AXIS]);
249 if (ydims.is_empty ())
250 ydims = Interval (0, 0);
252 b = Box(Interval(0,w), ydims);
259 for (int i = 0; i < text.length (); i++)
261 SCM sym = scm_vector_ref (coding_vector_,
262 scm_from_int((unsigned char) text[i]));
266 if (!scm_is_symbol (sym))
269 char const *chars = scm_i_string_chars (scm_symbol_to_string (sym));
271 int idx = orig_->name_to_index (chars);
273 char_box = orig_->get_indexed_char (idx);
275 char_box.scale (magnification_);
276 if (!char_box[X_AXIS].is_empty ())
278 w += char_box[X_AXIS][RIGHT];
280 ydims.unite (char_box[Y_AXIS]);
283 if (ydims.is_empty ())
284 ydims = Interval (0, 0);
286 b = Box (Interval (0, w), ydims);
293 Modified_font_metric::original_font () const
299 LY_DEFINE (ly_font_encoding_alist, "ly:font-encoding-alist",
302 "Given the Modified_font_metric @var{font}, return an "
303 "alist. Keys are input-name, input-vector, "
304 "output-name, output-table, mapping.")
306 Modified_font_metric *fm
307 = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
309 SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
310 return fm->coding_description_;
313 LY_DEFINE (ly_font_encoding, "ly:font-encoding",
316 "Return encoding of @var{font}.")
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 ());