+ 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 (string str)
+{
+ FT_Face face = open_ft_face (str);
+ 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 (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 (entry == SCM_BOOL_F)
+ 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 (size_t signed_idx) const
+{
+ if (SCM_HASHTABLE_P (lily_index_to_bbox_table_))