2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2004--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 // Necessary for supporting pango_context_new() and
21 // pango_context_set_font_map() in Pango < 1.22
22 #define PANGO_ENABLE_BACKEND
24 #include <pango/pangoft2.h>
25 #include <freetype/ftxf86.h>
32 #include "pango-font.hh"
33 #include "dimensions.hh"
34 #include "file-name.hh"
35 #include "international.hh"
36 #include "lookup.hh" // debugging
38 #include "string-convert.hh"
40 #include "all-font-metrics.hh"
41 #include "program-option.hh"
46 Pango_font::Pango_font (PangoFT2FontMap
*fontmap
,
47 PangoFontDescription
const *description
,
50 physical_font_tab_
= scm_c_make_hash_table (11);
51 PangoDirection pango_dir
= PANGO_DIRECTION_LTR
;
52 context_
= pango_context_new ();
53 pango_context_set_font_map (context_
, PANGO_FONT_MAP (fontmap
));
55 pango_description_
= pango_font_description_copy (description
);
56 attribute_list_
= pango_attr_list_new ();
58 // urgh. I don't understand this. Why isn't this 1/(scale *
59 // resolution * output_scale)
62 output_scale_
= output_scale
;
64 / (Real (PANGO_SCALE
) * Real (PANGO_RESOLUTION
) * output_scale
);
66 // ugh. Should make this configurable.
67 pango_context_set_language (context_
, pango_language_from_string ("en_US"));
68 pango_context_set_base_dir (context_
, pango_dir
);
69 pango_context_set_font_description (context_
, description
);
72 Pango_font::~Pango_font ()
74 pango_font_description_free (pango_description_
);
75 g_object_unref (context_
);
76 pango_attr_list_unref (attribute_list_
);
80 Pango_font::register_font_file (string filename
,
84 scm_hash_set_x (physical_font_tab_
,
85 ly_string2scm (ps_name
),
86 scm_list_2 (ly_string2scm (filename
),
87 scm_from_int (face_index
)));
91 Pango_font::derived_mark () const
93 scm_gc_mark (physical_font_tab_
);
97 get_glyph_index_name (char *s
,
100 sprintf (s
, "glyphIndex%lX", code
);
104 get_unicode_name (char *s
,
108 sprintf (s
, "u%lX", code
);
110 sprintf (s
, "uni%04lX", code
);
114 Pango_font::pango_item_string_stencil (PangoGlyphItem
const *glyph_item
) const
116 const int GLYPH_NAME_LEN
= 256;
117 char glyph_name
[GLYPH_NAME_LEN
];
119 PangoAnalysis
const *pa
= &(glyph_item
->item
->analysis
);
120 PangoGlyphString
*pgs
= glyph_item
->glyphs
;
122 PangoRectangle logical_rect
;
123 PangoRectangle ink_rect
;
124 pango_glyph_string_extents (pgs
, pa
->font
, &ink_rect
, &logical_rect
);
126 PangoFcFont
*fcfont
= PANGO_FC_FONT (pa
->font
);
128 FT_Face ftface
= pango_fc_font_lock_face (fcfont
);
130 Box
b (Interval (PANGO_LBEARING (logical_rect
),
131 PANGO_RBEARING (logical_rect
)),
132 Interval (-PANGO_DESCENT (ink_rect
),
133 PANGO_ASCENT (ink_rect
)));
137 char const *ps_name_str0
= FT_Get_Postscript_Name (ftface
);
138 FcPattern
*fcpat
= fcfont
->font_pattern
;
140 FcChar8
*file_name_as_ptr
= 0;
141 FcPatternGetString (fcpat
, FC_FILE
, 0, &file_name_as_ptr
);
143 // due to a bug in FreeType 2.3.7 and earlier we can't use
144 // ftface->face_index; it is always zero for some font formats,
145 // in particular TTCs which we are interested in
147 FcPatternGetInteger (fcpat
, FC_INDEX
, 0, &face_index
);
150 if (file_name_as_ptr
)
151 // Normalize file name.
152 file_name
= File_name ((char const *)file_name_as_ptr
).to_string ();
154 SCM glyph_exprs
= SCM_EOL
;
155 SCM
*tail
= &glyph_exprs
;
157 Index_to_charcode_map
const *cmap
= 0;
158 bool has_glyph_names
= ftface
->face_flags
& FT_FACE_FLAG_GLYPH_NAMES
;
159 if (!has_glyph_names
)
160 cmap
= all_fonts_global
->get_index_to_charcode_map (
161 file_name
, face_index
, ftface
);
163 bool is_ttf
= string (FT_Get_X11_Font_Format (ftface
)) == "TrueType";
164 bool cid_keyed
= false;
166 for (int i
= 0; i
< pgs
->num_glyphs
; i
++)
168 PangoGlyphInfo
*pgi
= pgs
->glyphs
+ i
;
170 PangoGlyph pg
= pgi
->glyph
;
171 PangoGlyphGeometry ggeo
= pgi
->geometry
;
174 Zero-width characters are valid Unicode characters,
175 but glyph lookups need to be skipped.
177 if (!(pg
^ PANGO_GLYPH_EMPTY
))
180 glyph_name
[0] = '\0';
183 FT_Error errorcode
= FT_Get_Glyph_Name (ftface
, pg
, glyph_name
,
187 _f ("FT_Get_Glyph_Name () error: %s",
188 freetype_error_string (errorcode
).c_str ()));
191 SCM char_id
= SCM_EOL
;
192 if (glyph_name
[0] == '\0'
195 && cmap
->find (pg
) != cmap
->end ())
197 FT_ULong char_code
= cmap
->find (pg
)->second
;
198 get_unicode_name (glyph_name
, char_code
);
201 if (glyph_name
[0] == '\0' && has_glyph_names
)
204 _f ("Glyph has no name, but font supports glyph naming.\n"
205 "Skipping glyph U+%0X, file %s",
206 pg
, file_name
.c_str ()));
210 if (glyph_name
== string (".notdef") && is_ttf
)
211 glyph_name
[0] = '\0';
213 if (glyph_name
[0] == '\0' && is_ttf
)
214 // Access by glyph index directly.
215 get_glyph_index_name (glyph_name
, pg
);
217 if (glyph_name
[0] == '\0')
221 char_id
= scm_from_uint32 (pg
);
224 char_id
= scm_from_locale_string (glyph_name
);
226 *tail
= scm_cons (scm_list_4 (scm_from_double (ggeo
.width
* scale_
),
227 scm_from_double (ggeo
.x_offset
* scale_
),
228 scm_from_double (- ggeo
.y_offset
* scale_
),
231 tail
= SCM_CDRLOC (*tail
);
234 pango_glyph_string_free (pgs
);
236 PangoFontDescription
*descr
= pango_font_describe (pa
->font
);
237 Real size
= pango_font_description_get_size (descr
)
238 / (Real (PANGO_SCALE
));
241 warning (_f ("no PostScript font name for font `%s'", file_name
));
246 && (file_name
.find (".otf") != NPOS
247 || file_name
.find (".cff") != NPOS
))
249 // UGH: kludge a PS name for OTF/CFF fonts.
250 string name
= file_name
;
251 ssize idx
= file_name
.find (".otf");
253 idx
= file_name
.find (".cff");
255 name
= name
.substr (0, idx
);
257 ssize slash_idx
= name
.rfind ('/');
258 if (slash_idx
!= NPOS
)
261 name
= name
.substr (slash_idx
,
262 name
.length () - slash_idx
);
265 string initial
= name
.substr (0, 1);
266 initial
= String_convert::to_upper (initial
);
267 name
= name
.substr (1, name
.length () - 1);
268 name
= String_convert::to_lower (name
);
269 ps_name
= initial
+ name
;
271 else if (ps_name_str0
)
272 ps_name
= ps_name_str0
;
274 if (ps_name
.length ())
276 ((Pango_font
*) this)->register_font_file (file_name
,
279 pango_fc_font_unlock_face (fcfont
);
281 SCM expr
= scm_list_5 (ly_symbol2scm ("glyph-string"),
282 ly_string2scm (ps_name
),
283 scm_from_double (size
),
284 scm_from_bool (cid_keyed
),
285 ly_quote_scm (glyph_exprs
));
287 return Stencil (b
, expr
);
290 warning (_ ("FreeType face has no PostScript font name"));
295 Pango_font::physical_font_tab () const
297 return physical_font_tab_
;
300 extern bool music_strings_to_paths
;
303 Pango_font::text_stencil (Output_def
* /* state */,
304 string str
, bool music_string
) const
307 The text assigned to a PangoLayout is automatically divided
308 into sections and reordered according to the Unicode
309 Bidirectional Algorithm, if necessary.
311 PangoLayout
*layout
= pango_layout_new (context_
);
312 pango_layout_set_text (layout
, str
.c_str (), -1);
313 GSList
*lines
= pango_layout_get_lines (layout
);
318 for (GSList
*l
= lines
; l
; l
= l
->next
)
320 PangoLayoutLine
*line
= (PangoLayoutLine
*) l
->data
;
321 GSList
*layout_runs
= line
->runs
;
323 for (GSList
*p
= layout_runs
; p
; p
= p
->next
)
325 PangoGlyphItem
*item
= (PangoGlyphItem
*) p
->data
;
326 Stencil item_stencil
= pango_item_string_stencil (item
);
328 item_stencil
.translate_axis (last_x
, X_AXIS
);
329 last_x
= item_stencil
.extent (X_AXIS
)[RIGHT
];
331 #if 0 // Check extents.
332 if (!item_stencil
.extent_box ()[X_AXIS
].is_empty ())
334 Stencil frame
= Lookup::frame (item_stencil
.extent_box (), 0.1, 0.1);
337 Stencil
dimless_frame (empty
, frame
.expr ());
338 dest
.add_stencil (frame
);
342 dest
.add_stencil (item_stencil
);
346 string name
= get_output_backend_name ();
347 string output_mod
= "scm output-" + name
;
348 SCM mod
= scm_c_resolve_module (output_mod
.c_str ());
350 bool has_utf8_string
= false;
352 if (ly_is_module (mod
))
354 SCM utf8_string
= ly_module_lookup (mod
, ly_symbol2scm ("utf-8-string"));
356 has_utf8_string should only be true when utf8_string is a
357 variable that is bound to a *named* procedure, i.e. not a
360 if (utf8_string
!= SCM_BOOL_F
361 && scm_procedure_name (SCM_VARIABLE_REF (utf8_string
)) != SCM_BOOL_F
)
362 has_utf8_string
= true;
365 bool to_paths
= music_strings_to_paths
;
368 Backends with the utf-8-string expression use it when
369 1) the -dmusic-strings-to-paths option is set
370 and `str' is not a music string, or
371 2) the -dmusic-strings-to-paths option is not set.
373 if (has_utf8_string
&& ((to_paths
&& !music_string
) || !to_paths
))
375 // For Pango based backends, we take a shortcut.
376 SCM exp
= scm_list_3 (ly_symbol2scm ("utf-8-string"),
377 ly_string2scm (description_string ()),
378 ly_string2scm (str
));
380 Box
b (Interval (0, 0), Interval (0, 0));
381 b
.unite (dest
.extent_box ());
382 return Stencil (b
, exp
);
389 Pango_font::description_string () const
391 char *descr_string
= pango_font_description_to_string (pango_description_
);
392 string
s (descr_string
);
393 g_free (descr_string
);
398 Pango_font::font_file_name () const
403 #endif // HAVE_PANGO_FT2