2 pango-font.cc -- implement Pango_font
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #define PANGO_ENABLE_BACKEND // ugh, why necessary?
10 #include <pango/pangoft2.h>
13 #include "pango-font.hh"
15 #include "dimensions.hh"
16 #include "file-name.hh"
24 Pango_font::Pango_font (PangoFT2FontMap
*fontmap
,
26 PangoFontDescription
*description
,
30 physical_font_tab_
= scm_c_make_hash_table (11);
31 PangoDirection pango_dir
= (dir
== RIGHT
)
33 : PANGO_DIRECTION_RTL
;
35 = pango_ft2_get_context (PANGO_RESOLUTION
, PANGO_RESOLUTION
);
36 // context_ = pango_ft2_font_map_create_context (fontmap);
38 pango_description_
= pango_font_description_copy (description
);
39 attribute_list_
= pango_attr_list_new ();
42 urgh. I don't understand this. Why isn't this 1/(scale *
43 resolution * output_scale)
47 scale_
= INCH_TO_BP
/ (Real (PANGO_SCALE
) * Real (PANGO_RESOLUTION
) * output_scale
);
50 ugh. Should make this configurable.
52 pango_context_set_language (context_
, pango_language_from_string ("en_US"));
53 pango_context_set_base_dir (context_
, pango_dir
);
54 pango_context_set_font_description (context_
, description
);
57 Pango_font::~Pango_font ()
59 pango_font_description_free (pango_description_
);
60 g_object_unref (context_
);
61 pango_attr_list_unref (attribute_list_
);
65 Pango_font::register_font_file (String filename
, String ps_name
)
67 scm_hash_set_x (physical_font_tab_
,
68 scm_makfrom0str (ps_name
.to_str0 ()),
69 scm_makfrom0str (filename
.to_str0 ()));
73 Pango_font::derived_mark () const
75 scm_gc_mark (physical_font_tab_
);
79 Pango_font::pango_item_string_stencil (PangoItem
*item
, String str
, Real dx
) const
81 const int GLYPH_NAME_LEN
= 256;
82 char glyph_name
[GLYPH_NAME_LEN
];
83 PangoAnalysis
*pa
= &(item
->analysis
);
84 PangoGlyphString
*pgs
= pango_glyph_string_new ();
86 pango_shape (str
.to_str0 () + item
->offset
,
87 item
->length
, pa
, pgs
);
89 PangoRectangle logical_rect
;
90 PangoRectangle ink_rect
;
91 pango_glyph_string_extents (pgs
, pa
->font
, &ink_rect
, &logical_rect
);
93 PangoFcFont
*fcfont
= G_TYPE_CHECK_INSTANCE_CAST (pa
->font
,
97 FT_Face ftface
= pango_fc_font_lock_face (fcfont
);
98 Box
b (Interval (PANGO_LBEARING (ink_rect
),
99 PANGO_RBEARING (ink_rect
)),
100 Interval (-PANGO_DESCENT (ink_rect
),
101 PANGO_ASCENT (ink_rect
)));
105 SCM glyph_exprs
= SCM_EOL
;
106 SCM
*tail
= &glyph_exprs
;
108 bool cid_keyed
= false;
109 for (int i
= 0; i
< pgs
->num_glyphs
; i
++)
111 PangoGlyphInfo
*pgi
= pgs
->glyphs
+ i
;
113 PangoGlyph pg
= pgi
->glyph
;
114 PangoGlyphGeometry ggeo
= pgi
->geometry
;
116 FT_Get_Glyph_Name (ftface
, pg
, glyph_name
, GLYPH_NAME_LEN
);
119 if (glyph_name
[0] == '\0')
125 char_id
= scm_from_int (pg
);
128 char_id
= scm_makfrom0str (glyph_name
);
129 *tail
= scm_cons (scm_list_3 (scm_from_double (ggeo
.x_offset
* scale_
131 scm_from_double (ggeo
.y_offset
* scale_
),
135 tail
= SCM_CDRLOC (*tail
);
138 PangoFontDescription
*descr
= pango_font_describe (pa
->font
);
139 Real size
= pango_font_description_get_size (descr
)
140 / (Real (PANGO_SCALE
));
142 FcPattern
*fcpat
= fcfont
->font_pattern
;
144 FcPatternGetString (fcpat
, FC_FILE
, 0, (FcChar8
**) & file_name
);
146 /* Normalize file name. */
147 // FIXME: memleak(s?), drop the #ifdef?
148 file_name
= File_name (file_name
).to_string ().get_copy_str0 ();
151 char const *ps_name_str0
= FT_Get_Postscript_Name (ftface
);
154 warning (_f ("no PostScript font name for font `%s'", file_name
));
159 && (String (file_name
).index (".otf") >= 0
160 || String (file_name
).index (".cff") >= 0))
163 /* UGH: kludge a PS name for OTF/CFF fonts. */
164 String name
= file_name
;
165 int idx
= max (String (file_name
).index (".otf"),
166 String (file_name
).index (".cff"));
168 name
= name
.left_string (idx
);
170 int slash_idx
= name
.index_last ('/');
172 name
= name
.right_string (name
.length () - slash_idx
- 1);
174 String initial
= name
.cut_string (0, 1);
176 name
= name
.nomid_string (0, 1);
178 ps_name
= initial
+ name
;
180 else if (ps_name_str0
)
181 ps_name
= ps_name_str0
;
183 if (ps_name
.length ())
185 ((Pango_font
*) this)->register_font_file (file_name
, ps_name
);
186 pango_fc_font_unlock_face (fcfont
);
188 SCM expr
= scm_list_5 (ly_symbol2scm ("glyph-string"),
189 scm_makfrom0str (ps_name
.to_str0 ()),
190 scm_from_double (size
),
191 scm_from_bool (cid_keyed
),
192 ly_quote_scm (glyph_exprs
));
194 return Stencil (b
, expr
);
197 warning (_ ("FreeType face has no PostScript font name"));
202 Pango_font::physical_font_tab () const
204 return physical_font_tab_
;
208 Pango_font::text_stencil (String str
) const
210 GList
*items
= pango_itemize (context_
,
212 0, str
.length (), attribute_list_
,
220 PangoItem
*item
= (PangoItem
*) ptr
->data
;
222 Stencil item_stencil
= pango_item_string_stencil (item
, str
, x
);
224 x
= item_stencil
.extent (X_AXIS
)[RIGHT
];
226 dest
.add_stencil (item_stencil
);
232 UGH. Should have flags per output format signifying supported
235 if (output_backend_global
!= "ps"
236 && output_backend_global
!= "eps")
239 For Pango based backends, we take a shortcut.
241 char *descr_string
= pango_font_description_to_string (pango_description_
);
243 = scm_list_3 (ly_symbol2scm ("utf-8-string"),
244 scm_makfrom0str (descr_string
),
245 scm_makfrom0str (str
.to_str0 ()));
247 g_free (descr_string
);
249 Box
b (Interval (0, 0), Interval (0, 0));
250 b
.unite (dest
.extent_box ());
251 return Stencil (b
, exp
);
254 #if 0 /* Check extents. */
255 if (!dest
.extent_box ()[X_AXIS
].is_empty ())
257 Stencil frame
= Lookup::frame (dest
.extent_box (), 0.1, 0.1);
260 Stencil
dimless_frame (empty
, frame
.expr ());
261 dest
.add_stencil (frame
);
269 Pango_font::font_file_name () const