2 open-type-font.cc -- implement Open_type_font
4 source file of the GNU LilyPond music typesetter
6 (c) 2004--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "open-type-font.hh"
11 #include <freetype/tttables.h>
14 #include "dimensions.hh"
15 #include "modified-font-metric.hh"
19 load_table (char const *tag_str
, FT_Face face
, FT_ULong
*length
)
22 FT_ULong tag
= FT_MAKE_TAG (tag_str
[0], tag_str
[1], tag_str
[2], tag_str
[3]);
24 int error_code
= FT_Load_Sfnt_Table (face
, tag
, 0, NULL
, length
);
27 FT_Byte
*buffer
= (FT_Byte
*) malloc (*length
);
29 error (_f ("can't allocate %d bytes", *length
));
31 error_code
= FT_Load_Sfnt_Table (face
, tag
, 0, buffer
, length
);
33 error (_f ("can't load font table: %s", tag_str
));
39 programming_error ("Cannot find OpenType table.");
47 Open_type_font::get_otf_table (String tag
) const
49 return ::get_otf_table (face_
, tag
);
53 load_scheme_table (char const *tag_str
, FT_Face face
)
56 FT_Byte
*buffer
= load_table (tag_str
, face
, &length
);
61 String
contents ((Byte
const *)buffer
, length
);
62 contents
= "(quote (" + contents
+ "))";
64 tab
= scm_c_eval_string (contents
.to_str0 ());
71 make_index_to_charcode_map (FT_Face face
)
73 Index_to_charcode_map m
;
77 for (charcode
= FT_Get_First_Char (face
, &gindex
); gindex
!= 0;
78 charcode
= FT_Get_Next_Char (face
, charcode
, &gindex
))
83 Open_type_font::~Open_type_font ()
93 get_otf_table (FT_Face face
, String tag
)
96 FT_Byte
*tab
= load_table (tag
.to_str0 (), face
, &len
);
98 return String (tab
, len
);
102 open_ft_face (String str
)
105 int error_code
= FT_New_Face (freetype2_library
, str
.to_str0 (), 0, &face
);
107 if (error_code
== FT_Err_Unknown_File_Format
)
108 error (_f ("unsupported font format: %s", str
.to_str0 ()));
110 error (_f ("unknown error: %d reading font file: %s", error_code
,
116 Open_type_font::make_otf (String str
)
118 FT_Face face
= open_ft_face (str
);
119 Open_type_font
*otf
= new Open_type_font (face
);
121 return otf
->self_scm ();
124 Open_type_font::Open_type_font (FT_Face face
)
127 lily_character_table_
= SCM_EOL
;
128 lily_global_table_
= SCM_EOL
;
129 lily_subfonts_
= SCM_EOL
;
131 lily_character_table_
= alist_to_hashq (load_scheme_table ("LILC", face_
));
132 lily_global_table_
= alist_to_hashq (load_scheme_table ("LILY", face_
));
133 lily_subfonts_
= load_scheme_table ("LILF", face_
);
134 index_to_charcode_map_
= make_index_to_charcode_map (face_
);
138 Open_type_font::derived_mark () const
140 scm_gc_mark (lily_character_table_
);
141 scm_gc_mark (lily_global_table_
);
142 scm_gc_mark (lily_subfonts_
);
146 Open_type_font::attachment_point (String glyph_name
) const
148 SCM sym
= ly_symbol2scm (glyph_name
.to_str0 ());
149 SCM entry
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
152 if (entry
== SCM_BOOL_F
)
155 SCM char_alist
= entry
;
156 SCM att_scm
= scm_cdr (scm_assq (ly_symbol2scm ("attachment"), char_alist
));
158 return point_constant
* ly_scm2offset (att_scm
);
162 Open_type_font::get_indexed_char (int signed_idx
) const
164 if (SCM_HASHTABLE_P (lily_character_table_
))
168 int code
= FT_Get_Glyph_Name (face_
, signed_idx
, name
, len
);
170 warning (_f ("FT_Get_Glyph_Name() returned error: %d", code
));
172 SCM sym
= ly_symbol2scm (name
);
173 SCM alist
= scm_hashq_ref (lily_character_table_
, sym
, SCM_BOOL_F
);
175 if (alist
!= SCM_BOOL_F
)
177 SCM bbox
= scm_cdr (scm_assq (ly_symbol2scm ("bbox"), alist
));
180 b
[X_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
181 bbox
= scm_cdr (bbox
);
182 b
[Y_AXIS
][LEFT
] = scm_to_double (scm_car (bbox
));
183 bbox
= scm_cdr (bbox
);
184 b
[X_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
185 bbox
= scm_cdr (bbox
);
186 b
[Y_AXIS
][RIGHT
] = scm_to_double (scm_car (bbox
));
187 bbox
= scm_cdr (bbox
);
189 b
.scale (point_constant
);
194 FT_UInt idx
= signed_idx
;
195 FT_Load_Glyph (face_
,
199 FT_Glyph_Metrics m
= face_
->glyph
->metrics
;
200 int hb
= m
.horiBearingX
;
201 int vb
= m
.horiBearingY
;
202 Box
b (Interval (-hb
, m
.width
- hb
),
203 Interval (-vb
, m
.height
- vb
));
205 b
.scale (design_size () / Real (face_
->units_per_EM
));
210 Open_type_font::name_to_index (String nm
) const
212 char *nm_str
= (char *) nm
.to_str0 ();
213 if (int idx
= FT_Get_Name_Index (face_
, nm_str
))
219 Open_type_font::index_to_charcode (int i
) const
221 return ((Open_type_font
*) this)->index_to_charcode_map_
[i
];
225 Open_type_font::count () const
227 return ((Open_type_font
*) this)->index_to_charcode_map_
.size ();
231 Open_type_font::design_size () const
233 SCM entry
= scm_hashq_ref (lily_global_table_
,
234 ly_symbol2scm ("design_size"),
237 Hmm. Design size is arbitrary for
238 non-design-size fonts. I vote for 1 -
239 which will trip errors more
243 return scm_to_double (entry
) * Real (point_constant
);
247 Open_type_font::sub_fonts () const
249 return lily_subfonts_
;
253 Open_type_font::get_char_table () const
255 return lily_character_table_
;
259 Open_type_font::get_subfonts () const
261 return lily_subfonts_
;
265 Open_type_font::get_global_table () const
267 return lily_global_table_
;
271 Open_type_font::font_name () const
273 return FT_Get_Postscript_Name (face_
);