+ for (; rfont; rfont = next)
+ {
+ next = rfont->next;
+ M17N_OBJECT_UNREF (rfont->info);
+ free (rfont);
+ rfont = next;
+ }
+}
+
+MFontList *
+mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size)
+{
+ MFontList *list;
+ MSymbol id = mfont__id (spec);
+ MPlist *pl, *p;
+ int num, i;
+
+ pl = msymbol_get (id, M_font_list);
+ if (pl)
+ num = (int) msymbol_get (id, M_font_list_len);
+ else
+ {
+ pl = mplist ();
+ num = 0;
+ MPLIST_DO (p, frame->font_driver_list)
+ {
+ if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx
+ : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype
+ : 1)
+ {
+ MFontDriver *driver = MPLIST_VAL (p);
+ num += (driver->list) (frame, pl, spec, 0);
+ }
+ }
+ msymbol_put (id, M_font_list, pl);
+ M17N_OBJECT_UNREF (pl);
+ msymbol_put (id, M_font_list_len, (void *) num);
+ }
+
+ if (num == 0)
+ return NULL;
+
+ MSTRUCT_MALLOC (list, MERROR_FONT);
+ MTABLE_MALLOC (list->fonts, num, MERROR_FONT);
+ for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl))
+ {
+ MFont *font = MPLIST_VAL (pl), *adjusted = font;
+
+ if (max_size == 0
+ || font->size == 0
+ || font->size < max_size)
+ {
+ list->fonts[i].font = font;
+ if (spec == request)
+ list->fonts[i].score = 0;
+ else
+ {
+ int resize_ratio;
+ MFont resized;
+
+ if (font->size > 0
+ && (resize_ratio = mfont_resize_ratio (font)) != 100)
+ {
+ resized = *font;
+ resized.size = font->size * 100 / resize_ratio;
+ adjusted = &resized;
+ }
+ list->fonts[i].score = font_score (adjusted, request);
+ }
+ i++;
+ }
+ }
+ if (i == 0)
+ {
+ free (list->fonts);
+ free (list);
+ return NULL;
+ }
+ list->nfonts = i;
+ if (spec != request)
+ qsort (list->fonts, i, sizeof (MFontScore), compare_font_score);
+ list->object = *spec;
+ mfont__merge (&list->object, request, 0);
+ list->object.type = MFONT_TYPE_OBJECT;
+ return list;
+}
+
+/** Open a font specified in FONT. */
+
+MRealizedFont *
+mfont__open (MFrame *frame, MFont *font, MFont *spec)
+{
+ MFontDriver *driver;
+ MRealizedFont *rfont;
+
+ if (font->source == MFONT_SOURCE_UNDECIDED)
+ MFATAL (MERROR_FONT);
+ if (font->type != MFONT_TYPE_OBJECT)
+ MFATAL (MERROR_FONT);
+ for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
+ rfont = rfont->next)
+ {
+ driver = rfont->driver;
+ if (rfont->font == font
+ && mplist_find_by_value (frame->font_driver_list, driver))
+ break;
+ }
+
+ if (! rfont)
+ {
+ driver = mplist_get (frame->font_driver_list,
+ font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
+ if (! driver)
+ MFATAL (MERROR_FONT);
+ }
+ return (driver->open) (frame, font, spec, rfont);
+}
+
+int
+mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c)
+{
+ MFontEncoding *encoding;
+ unsigned code;
+ MFontDriver *driver;
+
+ if (font->source == MFONT_SOURCE_UNDECIDED)
+ MFATAL (MERROR_FONT);
+ encoding = (font->encoding ? font->encoding : find_encoding (font));
+ if (! encoding->encoding_charset)
+ return 0;
+ if (encoding->repertory_charset)
+ {
+ code = ENCODE_CHAR (encoding->repertory_charset, c);
+ return (code != MCHAR_INVALID_CODE);
+ }
+ code = ENCODE_CHAR (encoding->encoding_charset, c);
+ if (code == MCHAR_INVALID_CODE)
+ return 0;
+ if (font->type == MFONT_TYPE_REALIZED)
+ driver = ((MRealizedFont *) font)->driver;
+ else
+ {
+ driver = mplist_get (frame->font_driver_list,
+ font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
+ if (! driver)
+ MFATAL (MERROR_FONT);
+ }
+ return (driver->has_char) (frame, font, spec, c, code);
+}
+
+unsigned
+mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c)
+{
+ MFontEncoding *encoding;
+ unsigned code;
+ MFontDriver *driver;
+
+ if (font->source == MFONT_SOURCE_UNDECIDED)
+ MFATAL (MERROR_FONT);
+ encoding = (font->encoding ? font->encoding : find_encoding (font));
+ if (! encoding->encoding_charset)
+ return MCHAR_INVALID_CODE;
+ if (font->source == MFONT_SOURCE_X && encoding->repertory_charset)
+ return (ENCODE_CHAR (encoding->repertory_charset, c));
+ code = ENCODE_CHAR (encoding->encoding_charset, c);
+ if (code == MCHAR_INVALID_CODE)
+ return MCHAR_INVALID_CODE;
+ if (font->type == MFONT_TYPE_REALIZED)
+ driver = ((MRealizedFont *) font)->driver;
+ else
+ {
+ driver = mplist_get (frame->font_driver_list,
+ font->source == MFONT_SOURCE_X ? Mx : Mfreetype);
+ if (! driver)
+ MFATAL (MERROR_FONT);
+ }
+ return (driver->encode_char) (frame, font, spec, code);
+}
+
+void
+mfont__get_metric (MGlyphString *gstring, int from, int to)
+{
+ MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
+ MRealizedFont *rfont = from_g->rface->rfont;
+
+ for (g = from_g; ; g++)
+ if (g == to_g || g->rface->rfont != rfont)
+ {
+ int idx = GLYPH_INDEX (g);