2 open-type-font.cc -- implement Open_type_font
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2007 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
)
97 int error_code
= FT_New_Face (freetype2_library
, str
.c_str (), 0, &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 ()
110 Open_type_font::make_otf (string str
)
112 FT_Face face
= open_ft_face (str
);
113 Open_type_font
*otf
= new Open_type_font (face
);
115 return otf
->self_scm ();
118 Open_type_font::Open_type_font (FT_Face face
)
121 lily_character_table_
= SCM_EOL
;
122 lily_global_table_
= SCM_EOL
;
123 lily_subfonts_
= SCM_EOL
;
124 lily_index_to_bbox_table_
= SCM_EOL
;
126 lily_character_table_
= alist_to_hashq (load_scheme_table ("LILC", face_
));
127 lily_global_table_
= alist_to_hashq (load_scheme_table ("LILY", face_
));
128 lily_subfonts_
= load_scheme_table ("LILF", face_
);
129 index_to_charcode_map_
= make_index_to_charcode_map (face_
);
131 lily_index_to_bbox_table_
= scm_c_make_hash_table (257);
135 Open_type_font::derived_mark () const
137 scm_gc_mark (lily_character_table_
);
138 scm_gc_mark (lily_global_table_
);
139 scm_gc_mark (lily_subfonts_
);
140 scm_gc_mark (lily_index_to_bbox_table_
);
144 Open_type_font::attachment_point (string glyph_name
) const
146 SCM sym
= ly_symbol2scm (glyph_name
.c_str ());
147 SCM entry
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
150 if (entry
== SCM_BOOL_F
)
153 SCM char_alist
= entry
;
154 SCM att_scm
= scm_cdr (scm_assq (ly_symbol2scm ("attachment"), char_alist
));
156 return point_constant
* ly_scm2offset (att_scm
);
160 Open_type_font::get_indexed_char (size_t signed_idx
) const
162 if (SCM_HASHTABLE_P (lily_index_to_bbox_table_
))
164 SCM box
= scm_hashq_ref (lily_index_to_bbox_table_
,
165 scm_from_unsigned (signed_idx
), SCM_BOOL_F
);
166 Box
*box_ptr
= Box::unsmob (box
);
171 if (SCM_HASHTABLE_P (lily_character_table_
))
173 const size_t len
= 256;
175 size_t code
= FT_Get_Glyph_Name (face_
, signed_idx
, name
, len
);
177 warning (_f ("FT_Get_Glyph_Name () Freetype error: %s",
178 freetype_error_string (code
)));
180 SCM sym
= ly_symbol2scm (name
);
181 SCM alist
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
183 if (alist
!= SCM_BOOL_F
)
185 SCM bbox
= scm_cdr (scm_assq (ly_symbol2scm ("bbox"), alist
));
188 b
[X_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
189 bbox
= scm_cdr (bbox
);
190 b
[Y_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
191 bbox
= scm_cdr (bbox
);
192 b
[X_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
193 bbox
= scm_cdr (bbox
);
194 b
[Y_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
195 bbox
= scm_cdr (bbox
);
197 b
.scale (point_constant
);
199 scm_hashq_set_x (lily_index_to_bbox_table_
,
200 scm_from_unsigned (signed_idx
),
206 FT_UInt idx
= signed_idx
;
207 FT_Load_Glyph (face_
,
211 FT_Glyph_Metrics m
= face_
->glyph
->metrics
;
212 int hb
= m
.horiBearingX
;
213 int vb
= m
.horiBearingY
;
214 Box
b (Interval (-hb
, m
.width
- hb
),
215 Interval (-vb
, m
.height
- vb
));
217 b
.scale (design_size () / Real (face_
->units_per_EM
));
222 Open_type_font::name_to_index (string nm
) const
224 char *nm_str
= (char *) nm
.c_str ();
225 if (size_t idx
= FT_Get_Name_Index (face_
, nm_str
))
232 Open_type_font::index_to_charcode (size_t i
) const
234 return ((Open_type_font
*) this)->index_to_charcode_map_
[i
];
238 Open_type_font::count () const
240 return ((Open_type_font
*) this)->index_to_charcode_map_
.size ();
244 Open_type_font::design_size () const
246 SCM entry
= scm_hashq_ref (lily_global_table_
,
247 ly_symbol2scm ("design_size"),
250 Hmm. Design size is arbitrary for
251 non-design-size fonts. I vote for 1 -
252 which will trip errors more
255 scm_from_unsigned (1));
256 return scm_to_double (entry
) * Real (point_constant
);
260 Open_type_font::sub_fonts () const
262 return lily_subfonts_
;
266 Open_type_font::get_char_table () const
268 return lily_character_table_
;
272 Open_type_font::get_subfonts () const
274 return lily_subfonts_
;
278 Open_type_font::get_global_table () const
280 return lily_global_table_
;
284 Open_type_font::font_name () const
286 return FT_Get_Postscript_Name (face_
);
291 Open_type_font::glyph_list () const
293 SCM retval
= SCM_EOL
;
296 for (int i
= 0; i
< face_
->num_glyphs
; i
++)
298 const size_t len
= 256;
300 size_t code
= FT_Get_Glyph_Name (face_
, i
, name
, len
);
302 warning (_f ("FT_Get_Glyph_Name () error: %s",
303 freetype_error_string (code
).c_str ()));
305 *tail
= scm_cons (scm_from_locale_string (name
), SCM_EOL
);
306 tail
= SCM_CDRLOC (*tail
);