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>
10 #include "modified-font-metric.hh"
11 #include "pango-font.hh"
12 #include "text-metrics.hh"
16 Modified_font_metric::Modified_font_metric (Font_metric *fm,
19 String input_encoding)
21 input_encoding_ = input_encoding;
22 coding_vector_ = SCM_EOL;
23 coding_mapping_ = SCM_EOL;
24 coding_table_ = SCM_EOL;
25 coding_description_ = SCM_EOL;
26 magnification_ = magnification;
28 SCM desc = fm->description_;
30 Real total_mag = magnification * scm_to_double (scm_cdr (desc));
33 description_ = scm_cons (scm_car (desc), scm_make_real (total_mag));
36 String metric_coding = orig_->coding_scheme ();
37 if (metric_coding != "FontSpecific"
38 && metric_coding != font_encoding)
39 warning (_f ("conflicting metric coding (%s) and font_encoding (%s)",
40 metric_coding, font_encoding));
42 if (input_encoding_ != ""
43 && input_encoding_ != "TeX"
44 && input_encoding_ != "ASCII"
45 && input_encoding_ != font_encoding)
47 coding_vector_ = scm_call_1 (ly_lily_module_constant ("get-coding-vector"),
48 scm_makfrom0str (font_encoding.to_str0 ()));
50 if (!ly_c_vector_p (coding_vector_))
52 programming_error ("get-coding-vector should return vector");
53 coding_vector_ = scm_c_make_vector (256, ly_symbol2scm (".notdef"));
56 coding_table_ = scm_call_1 (ly_lily_module_constant ("get-coding-table"),
57 scm_makfrom0str (font_encoding.to_str0 ()));
60 = scm_call_2 (ly_lily_module_constant ("make-encoding-mapping"),
64 coding_description_ = SCM_EOL;
66 = scm_acons (ly_symbol2scm ("input-name"),
67 scm_makfrom0str (input_encoding_.to_str0 ()),
70 = scm_acons (ly_symbol2scm ("input-vector"),
71 coding_vector_, coding_description_);
73 = scm_acons (ly_symbol2scm ("output-name"),
74 scm_makfrom0str (orig_->coding_scheme ().to_str0 ()),
77 = scm_acons (ly_symbol2scm ("output-table"),
81 = scm_acons (ly_symbol2scm ("char-mapping"),
88 Modified_font_metric::make_scaled_font_metric (Font_metric *fm, Real scaling,
95 if (scm_is_symbol (input_encoding))
96 input_encoding = scm_symbol_to_string (input_encoding);
98 String font_encoding_str = ly_symbol2string (font_encoding);
99 String input_encoding_str
100 = scm_is_string (input_encoding) ? ly_scm2string (input_encoding) : "";
102 Modified_font_metric *sfm = new Modified_font_metric (fm, scaling,
105 return sfm->self_scm ();
109 Modified_font_metric::design_size () const
111 return orig_->design_size ();
116 Modified_font_metric::get_indexed_char (int i) const
118 Box b = orig_->get_indexed_char (i);
119 b.scale (magnification_);
124 Modified_font_metric::get_ascii_char (int i) const
126 Box b = orig_->get_ascii_char (i);
127 b.scale (magnification_);
132 Modified_font_metric::count () const
134 return orig_->count ();
138 Modified_font_metric::attachment_point (String s) const
140 Offset o = orig_->attachment_point (s);
141 return o * magnification_;
145 Modified_font_metric::get_indexed_wxwy (int k) const
147 Offset o = orig_->get_indexed_wxwy (k);
148 return o * magnification_;
152 Modified_font_metric::name_to_index (String s) const
154 return orig_->name_to_index (s);
158 Modified_font_metric::index_to_charcode (int i) const
160 return orig_->index_to_charcode (i);
164 Modified_font_metric::index_to_ascii (int k) const
166 return orig_->index_to_ascii (k);
170 Modified_font_metric::coding_scheme () const
172 return input_encoding_;
176 Modified_font_metric::derived_mark () const
178 scm_gc_mark (coding_vector_);
179 scm_gc_mark (coding_description_);
180 scm_gc_mark (coding_table_);
181 scm_gc_mark (coding_mapping_);
184 /* TODO: put this klutchness behind ly:option switch. */
186 Modified_font_metric::tex_kludge (String text) const
190 for (int i = 0; i < text.length (); i++)
195 /* Accent marks use width of base letter */
196 if (i +1 < text.length ())
198 if (text[i+1]=='\'' || text[i+1]=='`' || text[i+1]=='"'
204 /* For string width \\ is a \ and \_ is a _. */
205 if (text[i+1]=='\\' || text[i+1]=='_')
209 for (i++; (i < text.length ()) && !isspace (text[i])
210 && text[i]!='{' && text[i]!='}'; i++)
213 /* Compensate for the auto-increment in the outer loop. */
217 case '{': // Skip '{' and '}'
222 Box b = get_ascii_char ((unsigned char)text[i]);
224 /* Use the width of 'x' for unknown characters */
225 if (b[X_AXIS].length () == 0)
226 b = get_ascii_char ((unsigned char)'x');
228 w += b[X_AXIS].length ();
229 ydims.unite (b[Y_AXIS]);
234 if (ydims.is_empty ())
235 ydims = Interval (0, 0);
237 return Box (Interval (0, w), ydims);
241 Modified_font_metric::text_stencil (String text) const
244 if (Pango_font * pf = dynamic_cast<Pango_font*> (orig_))
246 Stencil stc = pf->text_stencil (text);
248 Box b = stc.extent_box ();
250 b.scale (magnification_);
251 return Stencil (b, stc.expr());
254 return Font_metric::text_stencil (text);
258 Modified_font_metric::text_dimension (String text) const
260 SCM stext = scm_makfrom0str (text.to_str0 ());
261 Box b = lookup_tex_text_dimension (orig_, stext);
262 if (!b[Y_AXIS].is_empty ())
264 b.scale (magnification_);
268 if (input_encoding_ == "TeX")
269 b = tex_kludge (text);
270 else if (input_encoding_ == "ASCII"
271 || input_encoding_ == ""
272 || input_encoding_ == orig_->coding_scheme ())
278 for (int i = 0; i < text.length (); i++)
280 Box b = get_ascii_char ((unsigned char)text[i]);
282 w += b[X_AXIS].length ();
283 ydims.unite (b[Y_AXIS]);
285 if (ydims.is_empty ())
286 ydims = Interval (0, 0);
288 b = Box(Interval(0,w), ydims);
295 for (int i = 0; i < text.length (); i++)
297 SCM sym = scm_vector_ref (coding_vector_,
298 scm_from_int((unsigned char) text[i]));
302 if (!scm_is_symbol (sym))
305 char const *chars = scm_i_string_chars (scm_symbol_to_string (sym));
307 int idx = orig_->name_to_index (chars);
309 char_box = orig_->get_indexed_char (idx);
311 if (!char_box[X_AXIS].is_empty ())
313 w += char_box[X_AXIS][RIGHT];
315 ydims.unite (char_box[Y_AXIS]);
318 if (ydims.is_empty ())
319 ydims = Interval (0, 0);
321 b = Box (Interval (0, w), ydims);
322 b.scale (magnification_);
329 Modified_font_metric::original_font () const
335 LY_DEFINE (ly_font_encoding_alist, "ly:font-encoding-alist",
338 "Given the Modified_font_metric @var{font}, return an "
339 "alist. Keys are input-name, input-vector, "
340 "output-name, output-table, mapping.")
342 Modified_font_metric *fm
343 = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
345 SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
346 return fm->coding_description_;
349 LY_DEFINE (ly_font_encoding, "ly:font-encoding",
352 "Return encoding of @var{font}.")
354 Modified_font_metric *fm
355 = dynamic_cast<Modified_font_metric*> (unsmob_metrics (font));
356 SCM_ASSERT_TYPE (fm, font, SCM_ARG1, __FUNCTION__, "Modified_font_metric");
357 return ly_symbol2scm (fm->original_font ()->coding_scheme ().to_str0 ());
361 Modified_font_metric::sub_fonts () const
363 return orig_->sub_fonts();
367 Modified_font_metric::font_name () const
369 return original_font ()->font_name();