2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2004--2010 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 #include "open-type-font.hh"
26 #include <freetype/tttables.h>
28 #include "dimensions.hh"
29 #include "international.hh"
30 #include "modified-font-metric.hh"
34 load_table (char const *tag_str
, FT_Face face
, FT_ULong
*length
)
37 FT_ULong tag
= FT_MAKE_TAG (tag_str
[0], tag_str
[1], tag_str
[2], tag_str
[3]);
39 FT_Error error_code
= FT_Load_Sfnt_Table (face
, tag
, 0, NULL
, length
);
42 FT_Byte
*buffer
= (FT_Byte
*) malloc (*length
);
44 error (_f ("cannot allocate %lu bytes", *length
));
46 error_code
= FT_Load_Sfnt_Table (face
, tag
, 0, buffer
, length
);
48 error (_f ("cannot load font table: %s", tag_str
));
53 programming_error (_f ("Free type error: %s",
54 freetype_error_string (error_code
).c_str ()
61 Open_type_font::get_otf_table (string tag
) const
63 return ::get_otf_table (face_
, tag
);
67 load_scheme_table (char const *tag_str
, FT_Face face
)
70 FT_Byte
*buffer
= load_table (tag_str
, face
, &length
);
75 string
contents ((char const*)buffer
, length
);
76 contents
= "(quote (" + contents
+ "))";
78 tab
= scm_c_eval_string (contents
.c_str ());
85 Open_type_font::~Open_type_font ()
94 get_otf_table (FT_Face face
, string tag
)
97 FT_Byte
*tab
= load_table (tag
.c_str (), face
, &len
);
98 string
ret ((char const*) tab
, len
);
105 open_ft_face (string str
, FT_Long idx
)
108 FT_Error error_code
= FT_New_Face (freetype2_library
, str
.c_str (), idx
, &face
);
110 if (error_code
== FT_Err_Unknown_File_Format
)
111 error (_f ("unsupported font format: %s", str
.c_str ()));
113 error (_f ("error reading font file %s: %s",
115 freetype_error_string (error_code
).c_str ()));
120 Open_type_font::make_otf (string str
)
122 FT_Face face
= open_ft_face (str
, 0 /* index */);
123 Open_type_font
*otf
= new Open_type_font (face
);
125 return otf
->self_scm ();
128 Open_type_font::Open_type_font (FT_Face face
)
131 lily_character_table_
= SCM_EOL
;
132 lily_global_table_
= SCM_EOL
;
133 lily_subfonts_
= SCM_EOL
;
134 lily_index_to_bbox_table_
= SCM_EOL
;
136 lily_character_table_
= alist_to_hashq (load_scheme_table ("LILC", face_
));
137 lily_global_table_
= alist_to_hashq (load_scheme_table ("LILY", face_
));
138 lily_subfonts_
= load_scheme_table ("LILF", face_
);
139 index_to_charcode_map_
= make_index_to_charcode_map (face_
);
141 lily_index_to_bbox_table_
= scm_c_make_hash_table (257);
145 Open_type_font::derived_mark () const
147 scm_gc_mark (lily_character_table_
);
148 scm_gc_mark (lily_global_table_
);
149 scm_gc_mark (lily_subfonts_
);
150 scm_gc_mark (lily_index_to_bbox_table_
);
154 Open_type_font::attachment_point (string glyph_name
) const
156 SCM sym
= ly_symbol2scm (glyph_name
.c_str ());
157 SCM entry
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
160 if (entry
== SCM_BOOL_F
)
163 SCM char_alist
= entry
;
164 SCM att_scm
= scm_cdr (scm_assq (ly_symbol2scm ("attachment"), char_alist
));
166 return point_constant
* ly_scm2offset (att_scm
);
170 Open_type_font::get_indexed_char_dimensions (size_t signed_idx
) const
172 if (SCM_HASHTABLE_P (lily_index_to_bbox_table_
))
174 SCM box
= scm_hashq_ref (lily_index_to_bbox_table_
,
175 scm_from_unsigned (signed_idx
), SCM_BOOL_F
);
176 Box
*box_ptr
= Box::unsmob (box
);
181 if (SCM_HASHTABLE_P (lily_character_table_
))
183 const size_t len
= 256;
185 FT_Error code
= FT_Get_Glyph_Name (face_
, FT_UInt (signed_idx
),
186 name
, FT_UInt (len
));
188 warning (_f ("FT_Get_Glyph_Name () Freetype error: %s",
189 freetype_error_string (code
)));
191 SCM sym
= ly_symbol2scm (name
);
192 SCM alist
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
194 if (alist
!= SCM_BOOL_F
)
196 SCM bbox
= scm_cdr (scm_assq (ly_symbol2scm ("bbox"), alist
));
199 b
[X_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
200 bbox
= scm_cdr (bbox
);
201 b
[Y_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
202 bbox
= scm_cdr (bbox
);
203 b
[X_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
204 bbox
= scm_cdr (bbox
);
205 b
[Y_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
206 bbox
= scm_cdr (bbox
);
208 b
.scale (point_constant
);
210 scm_hashq_set_x (lily_index_to_bbox_table_
,
211 scm_from_unsigned (signed_idx
),
217 FT_UInt idx
= FT_UInt (signed_idx
);
218 FT_Load_Glyph (face_
, idx
, FT_LOAD_NO_SCALE
);
220 FT_Glyph_Metrics m
= face_
->glyph
->metrics
;
221 FT_Pos hb
= m
.horiBearingX
;
222 FT_Pos vb
= m
.horiBearingY
;
223 Box
b (Interval (Real (-hb
), Real (m
.width
- hb
)),
224 Interval (Real (-vb
), Real (m
.height
- vb
)));
226 b
.scale (design_size () / Real (face_
->units_per_EM
));
231 Open_type_font::name_to_index (string nm
) const
233 char *nm_str
= (char *) nm
.c_str ();
234 if (FT_UInt idx
= FT_Get_Name_Index (face_
, nm_str
))
241 Open_type_font::index_to_charcode (size_t i
) const
243 map
<FT_UInt
, FT_ULong
>::const_iterator iter
;
244 iter
= index_to_charcode_map_
.find (FT_UInt (i
));
246 if (iter
!= index_to_charcode_map_
.end ())
247 return (size_t) iter
->second
;
250 programming_error (_ ("Invalid index for character"));
256 Open_type_font::count () const
258 return index_to_charcode_map_
.size ();
262 Open_type_font::design_size () const
264 SCM entry
= scm_hashq_ref (lily_global_table_
,
265 ly_symbol2scm ("design_size"),
268 Hmm. Design size is arbitrary for
269 non-design-size fonts. I vote for 1 -
270 which will trip errors more
273 scm_from_unsigned (1));
274 return scm_to_double (entry
) * Real (point_constant
);
278 Open_type_font::sub_fonts () const
280 return lily_subfonts_
;
284 Open_type_font::get_char_table () const
286 return lily_character_table_
;
290 Open_type_font::get_subfonts () const
292 return lily_subfonts_
;
296 Open_type_font::get_global_table () const
298 return lily_global_table_
;
302 Open_type_font::font_name () const
304 return FT_Get_Postscript_Name (face_
);
308 Open_type_font::glyph_list () const
310 SCM retval
= SCM_EOL
;
313 for (int i
= 0; i
< face_
->num_glyphs
; i
++)
315 const size_t len
= 256;
317 FT_Error code
= FT_Get_Glyph_Name (face_
, i
, name
, len
);
319 warning (_f ("FT_Get_Glyph_Name () error: %s",
320 freetype_error_string (code
).c_str ()));
322 *tail
= scm_cons (scm_from_locale_string (name
), SCM_EOL
);
323 tail
= SCM_CDRLOC (*tail
);