X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Ffont-ft.c;h=a1b24a68b5ab71f59ff0a3eedc4110329106d5a5;hb=ef71335ceb286b3669919046ebccfbdf8cea9819;hp=4fab878e99b184cc146c40155a02e1c0e0caaf9d;hpb=ee6c2e0f2444981ab393e0fa87a3cb06c306e165;p=m17n%2Fm17n-lib.git diff --git a/src/font-ft.c b/src/font-ft.c index 4fab878..a1b24a6 100644 --- a/src/font-ft.c +++ b/src/font-ft.c @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with the m17n library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 02111-1307, USA. */ #include "config.h" @@ -44,12 +44,14 @@ #ifdef HAVE_FREETYPE #ifdef HAVE_FTBDF_H -#include +#include FT_BDF_H #endif static int mdebug_mask = MDEBUG_FONT; #ifdef HAVE_FONTCONFIG +#include + static FcConfig *fc_config; static MSymbol Mgeneric_family; #endif /* HAVE_FONTCONFIG */ @@ -81,8 +83,9 @@ typedef struct typedef struct { M17NObject control; - FT_Face ft_face; + FT_Face ft_face; /* This must be the 2nd member. */ MPlist *charmap_list; + int face_encapsulated; } MRealizedFontFT; typedef struct @@ -134,7 +137,6 @@ static int all_fonts_scaned; (s1) = alloca (len), (size) = len; \ for (p1 = (s1), p2 = (s2); *p2; p1++, p2++) \ *p1 = (*p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2); \ - while (p1 > (s1) && p1[-1] == ' ') p1--; \ *p1 = '\0'; \ } while (0) @@ -146,8 +148,11 @@ free_ft_rfont (void *object) { MRealizedFontFT *ft_rfont = object; - M17N_OBJECT_UNREF (ft_rfont->charmap_list); - FT_Done_Face (ft_rfont->ft_face); + if (! ft_rfont->face_encapsulated) + { + M17N_OBJECT_UNREF (ft_rfont->charmap_list); + FT_Done_Face (ft_rfont->ft_face); + } free (ft_rfont); } @@ -230,6 +235,74 @@ ft_get_charmaps (FT_Face ft_face) return plist; } +static MFontFT * +ft_gen_font (FT_Face ft_face) +{ + MFontFT *ft_info; + MFont *font; + char *buf; + int bufsize = 0; + char *stylename; + MSymbol family; + int size; + + if (FT_IS_SCALABLE (ft_face)) + size = ft_face->size->metrics.y_ppem; + else if (ft_face->num_fixed_sizes == 0) + return NULL; + else + size = ft_face->available_sizes[0].height; + + MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT); + font = &ft_info->font; + STRDUP_LOWER (buf, bufsize, ft_face->family_name); + family = msymbol (buf); + mfont__set_property (font, MFONT_FAMILY, family); + mfont__set_property (font, MFONT_WEIGHT, Mmedium); + mfont__set_property (font, MFONT_STYLE, Mr); + mfont__set_property (font, MFONT_STRETCH, Mnormal); + mfont__set_property (font, MFONT_ADSTYLE, Mnull); + mfont__set_property (font, MFONT_REGISTRY, Municode_bmp); + font->size = size * 10; + font->type = MFONT_TYPE_OBJECT; + font->source = MFONT_SOURCE_FT; + font->file = NULL; + + stylename = ft_face->style_name; + while (*stylename) + { + int i; + + for (i = 0; i < ft_to_prop_size; i++) + if (! strncasecmp (ft_to_prop[i].ft_style, stylename, + ft_to_prop[i].len)) + { + mfont__set_property (font, ft_to_prop[i].prop, + msymbol (ft_to_prop[i].val)); + stylename += ft_to_prop[i].len; + break; + } + if (i == ft_to_prop_size) + { + char *p1 = stylename + 1; + MSymbol sym; + + while (*p1 >= 'a' && *p1 <= 'z') p1++; + sym = msymbol__with_len (stylename, p1 - stylename); + for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++) + if (msymbol_get (sym, mfont__property_table[i].property)) + { + mfont__set_property (font, i, sym); + break; + } + stylename = p1; + } + while (*stylename && ! isalpha (*stylename)) + stylename++; + } + return ft_info; +} + #ifdef HAVE_FONTCONFIG typedef struct @@ -560,72 +633,14 @@ ft_add_font (char *filename) if (FT_New_Face (ft_library, filename, 0, &ft_face) != 0) return NULL; - if (! FT_IS_SCALABLE (ft_face)) - { - int reject; -#ifdef HAVE_FTBDF_H - BDF_PropertyRec prop; - - reject = FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop) == 0; - size = prop.u.integer * 10; -#else /* not HAVE_FTBDF_H */ - reject = 1; -#endif /* not HAVE_FTBDF_H */ - if (reject) - { - FT_Done_Face (ft_face); - return NULL; - } - } + ft_info = ft_gen_font (ft_face); + FT_Done_Face (ft_face); + if (! ft_info) + return NULL; - MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT); font = &ft_info->font; - STRDUP_LOWER (buf, bufsize, ft_face->family_name); - family = msymbol (buf); - mfont__set_property (font, MFONT_FAMILY, family); - mfont__set_property (font, MFONT_WEIGHT, Mmedium); - mfont__set_property (font, MFONT_STYLE, Mr); - mfont__set_property (font, MFONT_STRETCH, Mnormal); - mfont__set_property (font, MFONT_ADSTYLE, Mnull); - mfont__set_property (font, MFONT_REGISTRY, Municode_bmp); - font->type = MFONT_TYPE_OBJECT; - font->source = MFONT_SOURCE_FT; - font->size = size; font->file = msymbol (filename); - stylename = ft_face->style_name; - while (*stylename) - { - for (i = 0; i < ft_to_prop_size; i++) - if (! strncasecmp (ft_to_prop[i].ft_style, stylename, - ft_to_prop[i].len)) - { - mfont__set_property (font, ft_to_prop[i].prop, - msymbol (ft_to_prop[i].val)); - stylename += ft_to_prop[i].len; - break; - } - if (i == ft_to_prop_size) - { - char *p1 = stylename + 1; - MSymbol sym; - - while (*p1 >= 'a' && *p1 <= 'z') p1++; - sym = msymbol__with_len (stylename, p1 - stylename); - for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++) - if (msymbol_get (sym, mfont__property_table[i].property)) - { - mfont__set_property (font, i, sym); - break; - } - stylename = p1; - } - while (*stylename && ! isalpha (*stylename)) - stylename++; - } - - FT_Done_Face (ft_face); - plist = mplist_find_by_key (ft_font_list, family); if (plist) mplist_push (MPLIST_PLIST (plist), font->file, ft_info); @@ -1012,18 +1027,24 @@ ft_list_script (MSymbol script) plist = ft_list_char_list (char_list, NULL); #endif /* not HAVE_FONTCONFIG */ + mplist_push (ft_script_list, script, plist); return (plist); } static int -ft_check_otf (MFontFT *ft_info, MFontCapability *cap) +ft_check_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face) { #ifdef HAVE_OTF if (ft_info->otf == invalid_otf) return -1; if (! ft_info->otf) { - ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file)); +#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4) + if (ft_face) + ft_info->otf = OTF_open_ft_face (ft_face); + else +#endif + ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file)); if (! ft_info->otf) { ft_info->otf = invalid_otf; @@ -1053,10 +1074,11 @@ ft_check_otf (MFontFT *ft_info, MFontCapability *cap) } static int -ft_check_language (MFontFT *ft_info, MSymbol language) +ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face) { MText *mt; MText *extra; + int ft_face_allocaed = 0; int len, total_len; int i; @@ -1066,20 +1088,21 @@ ft_check_language (MFontFT *ft_info, MSymbol language) (FcChar8 *) MSYMBOL_NAME (language)) != FcLangDifferentLang)) return 0; - - if (! ft_info->charset) - return -1; -#else /* not HAVE_FONTCONFIG */ - FT_Face ft_face; - - if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, &ft_face)) - return 0; -#endif /* not HAVE_FONTCONFIG */ +#endif /* HAVE_FONTCONFIG */ mt = mlanguage_text (language); if (! mt || mtext_nchars (mt) == 0) return -1; + if (! ft_face) + { + char *filename = MSYMBOL_NAME (ft_info->font.file); + + if (FT_New_Face (ft_library, filename, 0, &ft_face)) + return -1; + ft_face_allocaed = 1; + } + len = mtext_nchars (mt); extra = mtext_get_prop (mt, 0, Mtext); total_len = len + (extra ? mtext_nchars (extra) : 0); @@ -1090,47 +1113,56 @@ ft_check_language (MFontFT *ft_info, MSymbol language) : mtext_ref_char (extra, i - len)); #ifdef HAVE_FONTCONFIG - if (FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse) + if (ft_info->charset + && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse) break; -#else /* not HAVE_FONTCONFIG */ +#endif /* HAVE_FONTCONFIG */ if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0) break; -#endif /* not HAVE_FONTCONFIG */ } -#ifndef HAVE_FONTCONFIG - FT_Done_Face (ft_face); -#endif /* not HAVE_FONTCONFIG */ + if (ft_face_allocaed) + FT_Done_Face (ft_face); return (i == total_len ? 0 : -1); } static int -ft_check_script (MFontFT *ft_info, MSymbol script) +ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face) { MPlist *char_list = mscript__char_list (script); -#ifdef HAVE_FONTCONFIG - if (! char_list || ! ft_info->charset) + if (! char_list) return -1; - MPLIST_DO (char_list, char_list) - if (FcCharSetHasChar (ft_info->charset, - (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse) - break; +#ifdef HAVE_FONTCONFIG + if (ft_info->charset) + { + MPLIST_DO (char_list, char_list) + if (FcCharSetHasChar (ft_info->charset, + (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse) + break; + } + else +#endif /* HAVE_FONTCONFIG */ + { + int ft_face_allocaed = 0; -#else /* not HAVE_FONTCONFIG */ - FT_Face ft_face; + if (! ft_face) + { + char *filename = MSYMBOL_NAME (ft_info->font.file); - if (! char_list - || FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, - &ft_face)) - return -1; + if (FT_New_Face (ft_library, filename, 0, &ft_face)) + return -1; + ft_face_allocaed = 1; + } - MPLIST_DO (char_list, char_list) - if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list)) == 0) - break; - FT_Done_Face (ft_face); -#endif /* not HAVE_FONTCONFIG */ + MPLIST_DO (char_list, char_list) + if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list)) + == 0) + break; + if (ft_face_allocaed) + FT_Done_Face (ft_face); + } return (MPLIST_TAIL_P (char_list) ? 0 : -1); } @@ -1219,7 +1251,7 @@ ft_list_capability (MSymbol capability) { for (pl = plist; ! MPLIST_TAIL_P (pl);) { - if (ft_check_script (MPLIST_VAL (pl), cap->script) < 0) + if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0) mplist_pop (pl); else pl = MPLIST_NEXT (pl); @@ -1230,7 +1262,7 @@ ft_list_capability (MSymbol capability) { for (pl = plist; ! MPLIST_TAIL_P (pl);) { - if (ft_check_otf (MPLIST_VAL (pl), cap) < 0) + if (ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0) mplist_pop (pl); else pl = MPLIST_NEXT (pl); @@ -1362,13 +1394,13 @@ ft_select (MFrame *frame, MFont *font, int limited_size) for (pl = plist; ! MPLIST_TAIL_P (pl);) { - if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap) < 0) + if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0) { mplist_pop (pl); continue; } if (cap->language - && ft_check_language (MPLIST_VAL (pl), cap->language) < 0) + && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0) mplist_pop (pl); else pl = MPLIST_NEXT (pl); @@ -2002,26 +2034,108 @@ 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) < 0) + && 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) < 0) + && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0) return -1; - if (cap->script_tag && ft_check_otf (ft_info, cap) < 0) + 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); +} + /* Internal API */ MFontDriver mfont__ft_driver = { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char, - ft_render, ft_list, ft_list_family_names, ft_check_capability}; + ft_render, ft_list, ft_list_family_names, ft_check_capability, + ft_encapsulate, ft_close }; int mfont__ft_init () @@ -2286,7 +2400,13 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, otf = ft_info->otf; if (! otf) { + MRealizedFontFT *ft_rfont = rfont->info; + +#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4) + otf = OTF_open_ft_face (ft_rfont->ft_face); +#else otf = OTF_open (MSYMBOL_NAME (ft_info->font.file)); +#endif if (! otf) { ft_info->otf = invalid_otf; @@ -2477,7 +2597,19 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, return to; simple_copy: - ft_find_metric (rfont, gstring, from, to); + for (i = 0; i < len; i++) + { + MGlyph *g = MGLYPH (from + i); + + if (! g->otf_encoded) + { + g->code = rfont->driver->encode_char (gstring->frame, (MFont *) rfont, + NULL, g->code); + g->otf_encoded = 1; + } + } + + rfont->driver->find_metric (rfont, gstring, from, to); for (i = 0; i < len; i++) { MGlyph temp = gstring->glyphs[from + i];