+ error (_f ("unsupported font format: %s", str.c_str ()));
+ else if (error_code)
+ error (_f ("error reading font file %s: %s",
+ str.c_str (),
+ freetype_error_string (error_code).c_str ()));
+ return face;
+}
+
+SCM
+Open_type_font::make_otf (const string &str)
+{
+ FT_Face face = open_ft_face (str, 0 /* index */);
+ Open_type_font *otf = new Open_type_font (face);
+
+ return otf->self_scm ();
+}
+
+Open_type_font::Open_type_font (FT_Face face)
+{
+ face_ = face;
+ lily_character_table_ = SCM_EOL;
+ lily_global_table_ = SCM_EOL;
+ lily_subfonts_ = SCM_EOL;
+ lily_index_to_bbox_table_ = SCM_EOL;
+
+ lily_character_table_ = alist_to_hashq (load_scheme_table ("LILC", face_));
+ lily_global_table_ = alist_to_hashq (load_scheme_table ("LILY", face_));
+ lily_subfonts_ = load_scheme_table ("LILF", face_);
+ index_to_charcode_map_ = make_index_to_charcode_map (face_);
+
+ lily_index_to_bbox_table_ = scm_c_make_hash_table (257);
+}
+
+void
+Open_type_font::derived_mark () const
+{
+ scm_gc_mark (lily_character_table_);
+ scm_gc_mark (lily_global_table_);
+ scm_gc_mark (lily_subfonts_);
+ scm_gc_mark (lily_index_to_bbox_table_);
+}
+
+Offset
+Open_type_font::attachment_point (const string &glyph_name) const
+{
+ SCM sym = ly_symbol2scm (glyph_name.c_str ());
+ SCM entry = scm_hashq_ref (lily_character_table_, sym, SCM_BOOL_F);
+
+ Offset o;
+ if (scm_is_false (entry))
+ return o;
+
+ SCM char_alist = entry;
+ SCM att_scm = scm_cdr (scm_assq (ly_symbol2scm ("attachment"), char_alist));
+
+ return point_constant * ly_scm2offset (att_scm);
+}
+
+Box
+Open_type_font::get_indexed_char_dimensions (size_t signed_idx) const
+{
+ if (SCM_HASHTABLE_P (lily_index_to_bbox_table_))