From 6018a2712ac2715f1c8522b68f08c133ba5130ce Mon Sep 17 00:00:00 2001 From: handa Date: Tue, 27 Apr 2004 07:31:31 +0000 Subject: [PATCH] Don't include FT_FREETYPE_H here. [HAVE_XFT2]: Include . (fontconfig_initialized, fc_config) [HAVE_XFT2]: New variables. (MFTInfo): New member charmap_index. (MFTInfo) [HAVE_XFT2]: New member xft_info. (check_otf_filename): Renamed from check_filename. Return value changed. (ft_set_property): This function deleted. (set_font_info): New function. (add_font_list): Argument changed. Add multiple fonts. (xft_list) [HAVE_XFT2]: New function. (ft_list) [not HAVE_XFT2]: New function. (ft_select): Add code for Xft. (close_ft): Likewise. (ft_open): Likewise. (ft_find_metric): Likewise. (ft_encode_char): Likewise. (ft_render): Likewise. --- src/font-ft.c | 402 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 255 insertions(+), 147 deletions(-) diff --git a/src/font-ft.c b/src/font-ft.c index 136a4c2..35a63a1 100644 --- a/src/font-ft.c +++ b/src/font-ft.c @@ -40,13 +40,19 @@ #include "face.h" #ifdef HAVE_FREETYPE -#include -#include FT_FREETYPE_H #ifdef HAVE_OTF #include #endif /* HAVE_OTF */ +#ifdef HAVE_XFT2 +/* Having Xft2 means having fontconfig. */ +#include + +int fontconfig_initialized = 0; +FcConfig *fc_config; +#endif /* not HAVE_XFT2 */ + static FT_Library ft_library; typedef struct @@ -63,176 +69,236 @@ typedef struct M17NObject control; MFont font; char *filename; + int otf_flag; /* This font 1: is OTF, 0: may be OTF, -1: is not OTF. */ MPlist *charmap_list; + int charmap_index; FT_Face ft_face; - int otf_flag; /* This font 1: is OTF, 0: may be OTF, -1: is not OTF. */ #ifdef HAVE_OTF OTF *otf; #endif /* HAVE_OTF */ +#ifdef HAVE_XFT2 + void *xft_info; +#endif /* not HAVE_XFT2 */ } MFTInfo; -/* List of FreeType fonts. Keys are family names, values are (MFTInfo - *) where MFTInfo->ft_face and MFTInfo->otf are NULL. */ +/* List of FreeType fonts. Keys are family names, values are plists + contains fonts of the corresponding family. In the deeper plist, + keys are Mt, values are (MFTInfo *). */ static MPlist *ft_font_list; -/** Return 1 iff the filename in DIRENTRY matches FreeType font file. - We select only TrueType/OpenType/Type1 fonts. - Used as the arg SELECT of scandir () in list_ft_in_dir (). */ +/** Return 0 if NAME implies TrueType or OpenType fonts. Othersize + return -1. */ static int -check_filename (const char *name) +check_otf_filename (const char *name) { int len = strlen (name); const char *ext = name + (len - 4); - if (len < 5) + if (len < 5 + || (memcmp (ext, ".ttf", 4) + && memcmp (ext, ".TTF", 4) + && memcmp (ext, ".otf", 4) + && memcmp (ext, ".OTF", 4))) return -1; - if (! memcmp (ext, ".ttf", 4) - || ! memcmp (ext, ".TTF", 4) - || ! memcmp (ext, ".otf", 4) - || ! memcmp (ext, ".OTF", 4)) - return 1; - if (! memcmp (ext, ".PFA", 4) - || ! memcmp (ext, ".pfa", 4) - || ! memcmp (ext, ".PFB", 4) - || ! memcmp (ext, ".pfb", 4)) - return 0; - return -1; + return 0; } +/** Setup members of FT_INFO from FT_FACE. Return the family name. */ + static MSymbol -ft_set_property (MFont *font, char *family_name, char *style_name) +set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family) { - MSymbol family; + MFont *font = &ft_info->font; MSymbol style; int len; char *buf, *p; + MPlist *charmap_list; + int unicode_bmp = -1, unicode_full = -1; + int i; MFONT_INIT (font); - font->property[MFONT_TYPE] = MFONT_TYPE_FT + 1; - mfont__set_property (font, MFONT_ADSTYLE, msymbol ("")); - len = strlen (family_name) + 1; - buf = (char *) alloca (len); - memcpy (buf, family_name, len); - for (p = buf; *p; p++) - if (*p >= 'A' && *p <= 'Z') - *p += 'a' - 'A'; - family = msymbol (buf); - mfont__set_property (font, MFONT_FAMILY, family); - - if (style_name) + if (family == Mt) { - len = strlen (style_name) + 1; + len = strlen (ft_face->family_name) + 1; buf = (char *) alloca (len); - memcpy (buf, style_name, len); + memcpy (buf, ft_face->family_name, len); for (p = buf; *p; p++) if (*p >= 'A' && *p <= 'Z') *p += 'a' - 'A'; - style = msymbol (buf); + family = msymbol (buf); } - else - style = Mnil; + mfont__set_property (font, MFONT_FAMILY, family); - if (style != Mnil) + if (ft_face->style_name) { - int i; - + len = strlen (ft_face->style_name) + 1; + buf = (char *) alloca (len); + memcpy (buf, ft_face->style_name, len); + for (p = buf; *p; p++) + if (*p >= 'A' && *p <= 'Z') + *p += 'a' - 'A'; + style = msymbol (buf); for (i = 0; i < ft_to_prop_size; i++) if (ft_to_prop[i].ft_style == style) { mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight); mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style); mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch); - return family; + break; } - } - mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium")); - mfont__set_property (font, MFONT_STYLE, msymbol ("r")); - mfont__set_property (font, MFONT_STRETCH, msymbol ("normal")); + } + else + i = ft_to_prop_size; + + if (i == ft_to_prop_size) + { + mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium")); + mfont__set_property (font, MFONT_STYLE, msymbol ("r")); + mfont__set_property (font, MFONT_STRETCH, msymbol ("normal")); + } + + font->property[MFONT_TYPE] = MFONT_TYPE_FT + 1; + mfont__set_property (font, MFONT_ADSTYLE, msymbol ("")); + + charmap_list = mplist (); + mplist_add (charmap_list, Mt, (void *) -1); + for (i = 0; i < ft_face->num_charmaps; i++) + { + char registry_buf[16]; + + sprintf (registry_buf, "%d-%d", + ft_face->charmaps[i]->platform_id, + ft_face->charmaps[i]->encoding_id); + mplist_add (charmap_list, msymbol (registry_buf), (void *) i); + if (ft_face->charmaps[i]->platform_id == 0) + { + if (ft_face->charmaps[i]->encoding_id == 3) + unicode_bmp = i; + else if (ft_face->charmaps[i]->encoding_id == 4) + unicode_full = i; + } + else if (ft_face->charmaps[i]->platform_id == 3) + { + if (ft_face->charmaps[i]->encoding_id == 1) + unicode_bmp = i; + else if (ft_face->charmaps[i]->encoding_id == 10) + unicode_full = i; + } + else if (ft_face->charmaps[i]->platform_id == 1 + && ft_face->charmaps[i]->encoding_id == 0) + mplist_add (charmap_list, msymbol ("apple-roman"), (void *) i); + } + if (unicode_bmp >= 0) + mplist_add (charmap_list, msymbol ("unicode-bmp"), (void *) unicode_bmp); + if (unicode_full >= 0) + mplist_add (charmap_list, msymbol ("unicode-full"), (void *) unicode_full); + + ft_info->charmap_list = charmap_list; + return family; } + static void -add_font_list (char *filename, int otf_flag) +add_font_list (MPlist *font_list) { - FT_Face ft_face; - MFTInfo *ft_info; - MSymbol family; - char registry_buf[16]; - int i; - - if (FT_New_Face (ft_library, filename, 0, &ft_face)) - return; + MPlist *plist; - if (ft_face->family_name && ((char *) ft_face->family_name)[0]) + MPLIST_DO (plist, font_list) { - int unicode_charmap_bmp = -1, unicode_charmap_full = -1; - - MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT); - family = ft_set_property (&ft_info->font, - (char *) ft_face->family_name, - (char *) ft_face->style_name); - ft_info->filename = strdup (filename); - ft_info->charmap_list = mplist (); - mplist_add (ft_info->charmap_list, Mt, (void *) -1); - for (i = 0; i < ft_face->num_charmaps; i++) + char *filename = MPLIST_VAL (plist); + FT_Face ft_face; + + if (FT_New_Face (ft_library, filename, 0, &ft_face) == 0) { - sprintf (registry_buf, "%d-%d", - ft_face->charmaps[i]->platform_id, - ft_face->charmaps[i]->encoding_id); - mplist_add (ft_info->charmap_list, msymbol (registry_buf), - (void *) i); - if (ft_face->charmaps[i]->platform_id == 0) - { - if (ft_face->charmaps[i]->encoding_id == 3) - unicode_charmap_bmp = i; - else if (ft_face->charmaps[i]->encoding_id == 4) - unicode_charmap_full = i; - } - else if (ft_face->charmaps[i]->platform_id == 3) + if (ft_face->family_name && ((char *) ft_face->family_name)[0]) { - if (ft_face->charmaps[i]->encoding_id == 1) - unicode_charmap_bmp = i; - else if (ft_face->charmaps[i]->encoding_id == 10) - unicode_charmap_full = i; + MSymbol family = MPLIST_KEY (plist); + MFTInfo *ft_info; + MPlist *p; + + MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT); + ft_info->filename = filename; + ft_info->otf_flag = check_otf_filename (filename); + family = set_font_info (ft_face, ft_info, family); + p = mplist_get (ft_font_list, family); + if (! p) + { + p = mplist (); + mplist_add (ft_font_list, family, p); + } + mplist_add (p, family, ft_info); } - else if (ft_face->charmaps[i]->platform_id == 1 - && ft_face->charmaps[i]->encoding_id == 0) - mplist_add (ft_info->charmap_list, msymbol ("apple-roman"), - (void *) i); + FT_Done_Face (ft_face); } - if (unicode_charmap_bmp >= 0) - mplist_add (ft_info->charmap_list, msymbol ("unicode-bmp"), - (void *) unicode_charmap_bmp); - if (unicode_charmap_full >= 0) - mplist_add (ft_info->charmap_list, msymbol ("unicode-full"), - (void *) unicode_charmap_full); - mplist_add (ft_font_list, family, ft_info); + else + free (filename); } - FT_Done_Face (ft_face); + M17N_OBJECT_UNREF (font_list); } -static void -build_font_list () +#ifdef HAVE_XFT2 +static MPlist * +xft_list (MSymbol family) { + FcPattern *pattern; + FcObjectSet *os; + FcFontSet *fs; MPlist *plist; + int i; + + if (! fc_config) + { + char *pathname; + struct stat buf; + + FcInit (); + fc_config = FcConfigGetCurrent (); + MPLIST_DO (plist, mfont_freetype_path) + if (MPLIST_STRING_P (plist) + && (pathname = MPLIST_STRING (plist)) + && stat (pathname, &buf) == 0) + FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname); + } + + pattern = FcPatternCreate (); + FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) (msymbol_name (family))); + os = FcObjectSetBuild (FC_FILE, NULL); + fs = FcFontList (fc_config, pattern, os); + plist = mplist (); + if (fs) + { + for (i = 0; i < fs->nfont; i++) + { + FcChar8 *filename; + + FcPatternGetString (fs->fonts[i], FC_FILE, 0, &filename); + mplist_add (plist, family, strdup ((char *) filename)); + } + FcFontSetDestroy (fs); + } + FcObjectSetDestroy (os); + FcPatternDestroy (pattern); + return plist; +} + +#else /* not HAVE_XFT2 */ +static MPlist * +ft_list () +{ + MPlist *font_list = mplist (), *plist; struct stat buf; char *pathname; - ft_font_list = mplist (); - MPLIST_DO (plist, mfont_freetype_path) if (MPLIST_STRING_P (plist) && (pathname = MPLIST_STRING (plist)) && stat (pathname, &buf) == 0) { if (S_ISREG (buf.st_mode)) - { - int result = check_filename (pathname); - - add_font_list (pathname, result > 0 ? 0 : -1); - } + mplist_add (font_list, Mt, strdup (pathname)); else if (S_ISDIR (buf.st_mode)) { int len = strlen (pathname); @@ -247,17 +313,19 @@ build_font_list () strcpy (path + len, "/"); len++; while ((dp = readdir (dir)) != NULL) - if ((result = check_filename (dp->d_name)) >= 0) - { - strcpy (path + len, dp->d_name); - add_font_list (path, result > 0 ? 0 : -1); - } + { + strcpy (path + len, dp->d_name); + mplist_add (font_list, Mt, strdup (path)); + } closedir (dir); } } } + return font_list; } +#endif + static MRealizedFont *ft_select (MFrame *, MFont *, MFont *, int); static int ft_open (MRealizedFont *); static void ft_close (MRealizedFont *); @@ -281,30 +349,47 @@ ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size) MRealizedFont *rfont; MSymbol family, registry; - if (! ft_font_list) - build_font_list (); best_font = NULL; best_score = 0; family = FONT_PROPERTY (spec, MFONT_FAMILY); + if (family == Mnil) + family = FONT_PROPERTY (request, MFONT_FAMILY); + if (family == Mnil) + return NULL; registry = FONT_PROPERTY (spec, MFONT_REGISTRY); if (registry == Mnil) registry = Mt; - MPLIST_DO (plist, ft_font_list) +#ifdef HAVE_XFT2 + if (! ft_font_list) + ft_font_list = mplist (); + plist = mplist_get (ft_font_list, family); + if (! plist) + { + add_font_list (xft_list (family)); + plist = mplist_get (ft_font_list, family); + if (! plist) + mplist_add (ft_font_list, family, plist = mplist ()); + } +#else /* not HAVE_XFT2 */ + if (! ft_font_list) { - MFTInfo *ft_info; + ft_font_list = mplist (); + add_font_list (ft_list ()); + } + plist = mplist_get (ft_font_list, family); + if (! plist) + return NULL; +#endif /* not HAVE_XFT2 */ + + MPLIST_DO (plist, plist) + { + MFTInfo *ft_info = MPLIST_VAL (plist); + MPlist *p = mplist_find_by_key (ft_info->charmap_list, registry); int score; - if (family) - { - plist = mplist_find_by_key (plist, family); - if (! plist) - break; - } - ft_info = (MFTInfo *) MPLIST_VAL (plist); - if (! mplist_find_by_key (ft_info->charmap_list, registry)) + if (! p) continue; - /* We always ignore FOUNDRY. */ ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY]; score = mfont__score (&ft_info->font, spec, request, limited_size); @@ -341,6 +426,10 @@ close_ft (void *object) if (ft_info->ft_face) FT_Done_Face (ft_info->ft_face); +#ifdef HAVE_XFT2 + if (ft_info->xft_info) + mwin__xft_close (ft_info->xft_info); +#endif /* HAVE_XFT2 */ #ifdef HAVE_OTF if (ft_info->otf) OTF_close (ft_info->otf); @@ -355,8 +444,8 @@ ft_open (MRealizedFont *rfont) { MFTInfo *ft_info; MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY); - int i; int mdebug_mask = MDEBUG_FONT; + int size; M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT); ft_info->font = ((MFTInfo *) rfont->info)->font; @@ -366,17 +455,26 @@ ft_open (MRealizedFont *rfont) rfont->info = ft_info; rfont->status = -1; + ft_info->ft_face = NULL; if (FT_New_Face (ft_library, ft_info->filename, 0, &ft_info->ft_face)) goto err; if (registry == Mnil) registry = Mt; - i = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry); - if (i >= 0 - && FT_Set_Charmap (ft_info->ft_face, ft_info->ft_face->charmaps[i])) + ft_info->charmap_index + = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry); + if (ft_info->charmap_index >= 0 + && FT_Set_Charmap (ft_info->ft_face, + ft_info->ft_face->charmaps[ft_info->charmap_index])) + goto err; + size = rfont->font.property[MFONT_SIZE] / 10; +#ifdef HAVE_XFT2 + ft_info->xft_info = mwin__xft_open (rfont->frame, ft_info->filename, size); + if (! ft_info->xft_info) goto err; - if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, - rfont->font.property[MFONT_SIZE] / 10)) +#else /* not HAVE_XFT2 */ + if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, size)) goto err; +#endif /* not HAVE_XFT2 */ MDEBUG_PRINT1 (" [FT-FONT] o %s\n", ft_info->filename); rfont->status = 1; @@ -432,6 +530,9 @@ ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring, } else { +#ifdef HAVE_XFT2 + mwin__xft_get_metric (ft_info->xft_info, ft_info->ft_face, g); +#else /* not HAVE_XFT2 */ FT_Glyph_Metrics *metrics; FT_UInt code; @@ -447,6 +548,7 @@ ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring, g->width = metrics->horiAdvance >> 6; g->ascent = metrics->horiBearingY >> 6; g->descent = (metrics->height - metrics->horiBearingY) >> 6; +#endif /* not HAVE_XFT2 */ } } } @@ -468,11 +570,6 @@ ft_encode_char (MRealizedFont *rfont, int c, unsigned ignored) code = FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) c); if (! code) return MCHAR_INVALID_CODE; -#if 0 - FT_Load_Glyph (ft_info->ft_face, code, FT_LOAD_NO_SCALE); - return (ft_info->ft_face->glyph->metrics.width > 0 - ? (unsigned) c : MCHAR_INVALID_CODE); -#endif return ((unsigned) c); } @@ -491,18 +588,29 @@ ft_render (MDrawWindow win, int x, int y, MGlyphString *gstring, MGlyph *from, MGlyph *to, int reverse, MDrawRegion region) { + MFTInfo *ft_info; + FT_Face ft_face; MRealizedFace *rface = from->rface; +#ifndef HAVE_XFT2 MFrame *frame = rface->frame; - MFTInfo *ft_info; - FT_Face ft_face = NULL; FT_Int32 load_flags = FT_LOAD_RENDER; MGlyph *g; int i, j; MPointTable point_table[8]; +#endif /* not HAVE_XFT2 */ if (from == to) return; + /* It is assured that the all glyphs in the current range use the + same realized face. */ + ft_info = (MFTInfo *) rface->rfont->info; + ft_face = ft_info->ft_face; + +#ifdef HAVE_XFT2 + mwin__xft_render (win, x, y, gstring, from, to, reverse, region, + ft_info->xft_info, ft_face); +#else /* not HAVE_XFT2 */ if (! gstring->anti_alias) { #ifdef FT_LOAD_TARGET_MONO @@ -512,11 +620,6 @@ ft_render (MDrawWindow win, int x, int y, #endif } - /* It is assured that the all glyphs in the current range use the - same realized face. */ - ft_info = (MFTInfo *) rface->rfont->info; - ft_face = ft_info->ft_face; - for (i = 0; i < 8; i++) point_table[i].p = point_table[i].points; @@ -600,6 +703,7 @@ ft_render (MDrawWindow win, int x, int y, point_table[0].points, point_table[0].p - point_table[0].points, region); } +#endif /* not HAVE_XFT2 */ } @@ -646,16 +750,20 @@ mfont__ft_init () void mfont__ft_fini () { - MPlist *plist; + MPlist *plist, *p; if (ft_font_list) { MPLIST_DO (plist, ft_font_list) { - MFTInfo *ft_info = (MFTInfo *) MPLIST_VAL (plist); - free (ft_info->filename); - M17N_OBJECT_UNREF (ft_info->charmap_list); - free (ft_info); + MPLIST_DO (p, MPLIST_VAL (plist)) + { + MFTInfo *ft_info = (MFTInfo *) MPLIST_VAL (p); + free (ft_info->filename); + M17N_OBJECT_UNREF (ft_info->charmap_list); + free (ft_info); + } + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); } M17N_OBJECT_UNREF (ft_font_list); ft_font_list = NULL; -- 1.7.10.4