2 open-type-font.cc -- implement Open_type_font
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "open-type-font.hh"
15 #include <freetype/tttables.h>
17 #include "dimensions.hh"
18 #include "international.hh"
19 #include "modified-font-metric.hh"
23 load_table (char const *tag_str
, FT_Face face
, FT_ULong
*length
)
26 FT_ULong tag
= FT_MAKE_TAG (tag_str
[0], tag_str
[1], tag_str
[2], tag_str
[3]);
28 int error_code
= FT_Load_Sfnt_Table (face
, tag
, 0, NULL
, length
);
31 FT_Byte
*buffer
= (FT_Byte
*) malloc (*length
);
33 error (_f ("cannot allocate %lu bytes", *length
));
35 error_code
= FT_Load_Sfnt_Table (face
, tag
, 0, buffer
, length
);
37 error (_f ("cannot load font table: %s", tag_str
));
42 programming_error (_f ("Free type error: %s",
43 freetype_error_string (error_code
).c_str ()
50 Open_type_font::get_otf_table (string tag
) const
52 return ::get_otf_table (face_
, tag
);
56 load_scheme_table (char const *tag_str
, FT_Face face
)
59 FT_Byte
*buffer
= load_table (tag_str
, face
, &length
);
64 string
contents ((char const*)buffer
, length
);
65 contents
= "(quote (" + contents
+ "))";
67 tab
= scm_c_eval_string (contents
.c_str ());
74 Open_type_font::~Open_type_font ()
83 get_otf_table (FT_Face face
, string tag
)
86 FT_Byte
*tab
= load_table (tag
.c_str (), face
, &len
);
87 string
ret ((char const*) tab
, len
);
94 open_ft_face (string str
, FT_Long idx
)
97 int error_code
= FT_New_Face (freetype2_library
, str
.c_str (), idx
, &face
);
99 if (error_code
== FT_Err_Unknown_File_Format
)
100 error (_f ("unsupported font format: %s", str
.c_str ()));
102 error (_f ("error reading font file %s: %s",
104 freetype_error_string (error_code
).c_str ()));
109 Open_type_font::make_otf (string str
)
111 FT_Face face
= open_ft_face (str
, 0 /* index */);
112 Open_type_font
*otf
= new Open_type_font (face
);
114 return otf
->self_scm ();
117 Open_type_font::Open_type_font (FT_Face face
)
120 lily_character_table_
= SCM_EOL
;
121 lily_global_table_
= SCM_EOL
;
122 lily_subfonts_
= SCM_EOL
;
123 lily_index_to_bbox_table_
= SCM_EOL
;
125 lily_character_table_
= alist_to_hashq (load_scheme_table ("LILC", face_
));
126 lily_global_table_
= alist_to_hashq (load_scheme_table ("LILY", face_
));
127 lily_subfonts_
= load_scheme_table ("LILF", face_
);
128 index_to_charcode_map_
= make_index_to_charcode_map (face_
);
130 lily_index_to_bbox_table_
= scm_c_make_hash_table (257);
134 Open_type_font::derived_mark () const
136 scm_gc_mark (lily_character_table_
);
137 scm_gc_mark (lily_global_table_
);
138 scm_gc_mark (lily_subfonts_
);
139 scm_gc_mark (lily_index_to_bbox_table_
);
143 Open_type_font::attachment_point (string glyph_name
) const
145 SCM sym
= ly_symbol2scm (glyph_name
.c_str ());
146 SCM entry
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
149 if (entry
== SCM_BOOL_F
)
152 SCM char_alist
= entry
;
153 SCM att_scm
= scm_cdr (scm_assq (ly_symbol2scm ("attachment"), char_alist
));
155 return point_constant
* ly_scm2offset (att_scm
);
159 Open_type_font::get_indexed_char (size_t signed_idx
) const
161 if (SCM_HASHTABLE_P (lily_index_to_bbox_table_
))
163 SCM box
= scm_hashq_ref (lily_index_to_bbox_table_
,
164 scm_from_unsigned (signed_idx
), SCM_BOOL_F
);
165 Box
*box_ptr
= Box::unsmob (box
);
170 if (SCM_HASHTABLE_P (lily_character_table_
))
172 const size_t len
= 256;
174 size_t code
= FT_Get_Glyph_Name (face_
, signed_idx
, name
, len
);
176 warning (_f ("FT_Get_Glyph_Name () Freetype error: %s",
177 freetype_error_string (code
)));
179 SCM sym
= ly_symbol2scm (name
);
180 SCM alist
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
182 if (alist
!= SCM_BOOL_F
)
184 SCM bbox
= scm_cdr (scm_assq (ly_symbol2scm ("bbox"), alist
));
187 b
[X_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
188 bbox
= scm_cdr (bbox
);
189 b
[Y_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
190 bbox
= scm_cdr (bbox
);
191 b
[X_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
192 bbox
= scm_cdr (bbox
);
193 b
[Y_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
194 bbox
= scm_cdr (bbox
);
196 b
.scale (point_constant
);
198 scm_hashq_set_x (lily_index_to_bbox_table_
,
199 scm_from_unsigned (signed_idx
),
205 FT_UInt idx
= signed_idx
;
206 FT_Load_Glyph (face_
,
210 FT_Glyph_Metrics m
= face_
->glyph
->metrics
;
211 int hb
= m
.horiBearingX
;
212 int vb
= m
.horiBearingY
;
213 Box
b (Interval (-hb
, m
.width
- hb
),
214 Interval (-vb
, m
.height
- vb
));
216 b
.scale (design_size () / Real (face_
->units_per_EM
));
221 Open_type_font::name_to_index (string nm
) const
223 char *nm_str
= (char *) nm
.c_str ();
224 if (size_t idx
= FT_Get_Name_Index (face_
, nm_str
))
231 Open_type_font::index_to_charcode (size_t i
) const
233 return ((Open_type_font
*) this)->index_to_charcode_map_
[i
];
237 Open_type_font::count () const
239 return ((Open_type_font
*) this)->index_to_charcode_map_
.size ();
243 Open_type_font::design_size () const
245 SCM entry
= scm_hashq_ref (lily_global_table_
,
246 ly_symbol2scm ("design_size"),
249 Hmm. Design size is arbitrary for
250 non-design-size fonts. I vote for 1 -
251 which will trip errors more
254 scm_from_unsigned (1));
255 return scm_to_double (entry
) * Real (point_constant
);
259 Open_type_font::sub_fonts () const
261 return lily_subfonts_
;
265 Open_type_font::get_char_table () const
267 return lily_character_table_
;
271 Open_type_font::get_subfonts () const
273 return lily_subfonts_
;
277 Open_type_font::get_global_table () const
279 return lily_global_table_
;
283 Open_type_font::font_name () const
285 return FT_Get_Postscript_Name (face_
);
290 Open_type_font::glyph_list () const
292 SCM retval
= SCM_EOL
;
295 for (int i
= 0; i
< face_
->num_glyphs
; i
++)
297 const size_t len
= 256;
299 size_t code
= FT_Get_Glyph_Name (face_
, i
, name
, len
);
301 warning (_f ("FT_Get_Glyph_Name () error: %s",
302 freetype_error_string (code
).c_str ()));
304 *tail
= scm_cons (scm_from_locale_string (name
), SCM_EOL
);
305 tail
= SCM_CDRLOC (*tail
);