+static void
+ft_list_family_names (MFrame *frame, MPlist *plist)
+{
+ MPlist *pl;
+
+ if (! ft_font_list)
+ {
+#ifdef HAVE_FONTCONFIG
+ fc_init_font_list ();
+#else /* not HAVE_FONTCONFIG */
+ ft_init_font_list ();
+#endif /* not HAVE_FONTCONFIG */
+ }
+
+ MPLIST_DO (pl, ft_font_list)
+ {
+ MSymbol family = MPLIST_KEY (pl);
+ MPlist *p;
+
+#ifdef HAVE_FONTCONFIG
+ if (msymbol_get (family, Mgeneric_family) != Mnil)
+ continue;
+#endif /* HAVE_FONTCONFIG */
+ MPLIST_DO (p, plist)
+ {
+ MSymbol sym = MPLIST_SYMBOL (p);
+
+ if (sym == family)
+ break;
+ if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0)
+ {
+ mplist_push (p, Msymbol, family);
+ break;
+ }
+ }
+ if (MPLIST_TAIL_P (p))
+ mplist_push (p, Msymbol, family);
+ }
+}
+
+static int
+ft_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+ MFontFT *ft_info = (MFontFT *) rfont->font;
+ MRealizedFontFT *ft_rfont = rfont->info;
+ MFontCapability *cap = mfont__get_capability (capability);
+
+ if (cap->script != Mnil
+ && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
+ return -1;
+ if (cap->language != Mnil
+ && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
+ return -1;
+ if (cap->script_tag && ft_check_otf (ft_info, cap, ft_rfont->ft_face) < 0)
+ return -1;
+ return 0;
+}
+
+static MRealizedFont *
+ft_encapsulate (MFrame *frame, MSymbol data_type, void *data)
+{
+ MFontFT *ft_info;
+ MRealizedFont *rfont;
+ MRealizedFontFT *ft_rfont;
+ FT_Face ft_face;
+
+ if (data_type == Mfontconfig)
+ {
+#ifdef HAVE_FONTCONFIG
+ FcPattern *pattern = data;
+
+ if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
+ != FcResultMatch)
+ return NULL;
+ ft_info = fc_gen_font (pattern, NULL);
+#else /* not HAVE_FONTCONFIG */
+ return NULL;
+#endif /* not HAVE_FONTCONFIG */
+ }
+ else if (data_type == Mfreetype)
+ {
+ ft_face = data;
+ ft_info = ft_gen_font (ft_face);
+ }
+ else
+ return NULL;
+
+ M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
+ ft_rfont->ft_face = ft_face;
+ ft_rfont->face_encapsulated = 1;
+
+ MDEBUG_DUMP (" [FONT-FT] encapsulating ", (char *) ft_face->family_name,);
+
+ MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
+ rfont->font = (MFont *) ft_info;
+ rfont->info = ft_rfont;
+ rfont->fontp = ft_face;
+ rfont->driver = &mfont__ft_driver;
+ rfont->spec = ft_info->font;
+ rfont->spec.type = MFONT_TYPE_REALIZED;
+ rfont->frame = frame;
+ rfont->ascent = ft_face->size->metrics.ascender >> 6;
+ rfont->descent = - ft_face->size->metrics.descender >> 6;
+ rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
+ rfont->baseline_offset = 0;
+#ifdef HAVE_FTBDF_H
+ {
+ BDF_PropertyRec prop;
+
+ if (! FT_IS_SCALABLE (ft_face)
+ && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
+ {
+ rfont->baseline_offset = prop.u.integer;
+ rfont->ascent += prop.u.integer;
+ rfont->descent -= prop.u.integer;
+ }
+ }
+#endif /* HAVE_FTBDF_H */
+ if (FT_IS_SCALABLE (ft_face))
+ rfont->average_width = 0;
+ else
+ rfont->average_width = ft_face->available_sizes->width;
+ rfont->next = MPLIST_VAL (frame->realized_font_list);
+ MPLIST_VAL (frame->realized_font_list) = rfont;
+
+ return rfont;
+}
+
+static void
+ft_close (MRealizedFont *rfont)
+{
+ if (! rfont->encapsulating)
+ return;
+ free (rfont->font);
+ M17N_OBJECT_UNREF (rfont->info);
+ free (rfont);
+}
+
+