X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffcfreetype.c;h=f85e2f8931eae1bc8b2305829ce355a9e6a08c37;hb=5b8e43a48ea1a5fb4e54dd12fe965439df2bf95d;hp=39aaa794da7ff85953b8c6a5f1ebef7d563c280b;hpb=97bde49a2b791de9ad66aed97ca07c22302da60d;p=fontconfig.git diff --git a/src/fcfreetype.c b/src/fcfreetype.c index 39aaa79..f85e2f8 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -44,34 +44,27 @@ THE SOFTWARE. */ +#include "fcint.h" #include #include #include -#include "fcint.h" #include #include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H #include FT_TRUETYPE_TABLES_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_IDS_H #include FT_TYPE1_TABLES_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_INTERNAL_TRUETYPE_TYPES_H #if HAVE_FT_GET_X11_FONT_FORMAT #include FT_XFREE86_H #endif - #if HAVE_FT_GET_BDF_PROPERTY #include FT_BDF_H #include FT_MODULE_H -#define HAS_BDF_PROPERTY(f) ((f) && (f)->driver && \ - (f)->driver->root.clazz->get_interface) -#define MY_Get_BDF_Property(f,n,p) (HAS_BDF_PROPERTY(f) ? \ - FT_Get_BDF_Property(f,n,p) : \ - FT_Err_Invalid_Argument) #endif +#include "ftglue.h" + +#if HAVE_WARNING_CPP_DIRECTIVE #if !HAVE_FT_GET_BDF_PROPERTY #warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later" #endif @@ -79,6 +72,7 @@ #if !HAVE_FT_GET_PS_FONT_INFO #warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later" #endif +#endif /* * Keep Han languages separated by eliminating languages @@ -95,7 +89,7 @@ static const struct { { 20, (const FcChar8 *) "zh-tw" }, }; -#define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0]) +#define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0]) FcBool FcFreeTypeIsExclusiveLang (const FcChar8 *lang) @@ -104,16 +98,16 @@ FcFreeTypeIsExclusiveLang (const FcChar8 *lang) for (i = 0; i < NUM_CODE_PAGE_RANGE; i++) { - if (FcLangCompare (lang, FcCodePageRange[i].lang) != FcLangDifferentLang) + if (FcLangCompare (lang, FcCodePageRange[i].lang) == FcLangEqual) return FcTrue; } return FcFalse; } typedef struct { - FT_UShort platform_id; - FT_UShort encoding_id; - char *fromcode; + const FT_UShort platform_id; + const FT_UShort encoding_id; + const char fromcode[12]; } FcFtEncoding; #define TT_ENCODING_DONT_CARE 0xffff @@ -135,18 +129,18 @@ static const FcFtEncoding fcFtEncoding[] = { { TT_PLATFORM_ISO, TT_ISO_ID_8859_1, "ISO-8859-1" }, }; -#define NUM_FC_FT_ENCODING (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0])) +#define NUM_FC_FT_ENCODING (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0])) typedef struct { - FT_UShort platform_id; - FT_UShort language_id; - char *lang; + const FT_UShort platform_id; + const FT_UShort language_id; + const char lang[8]; } FcFtLanguage; #define TT_LANGUAGE_DONT_CARE 0xffff static const FcFtLanguage fcFtLanguage[] = { - { TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE, 0 }, + { TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE, "" }, { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ENGLISH, "en" }, { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FRENCH, "fr" }, { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GERMAN, "de" }, @@ -545,11 +539,11 @@ static const FcFtLanguage fcFtLanguage[] = { { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" }, }; -#define NUM_FC_FT_LANGUAGE (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0])) +#define NUM_FC_FT_LANGUAGE (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0])) typedef struct { FT_UShort language_id; - char *fromcode; + char fromcode[12]; } FcMacRomanFake; static const FcMacRomanFake fcMacRomanFake[] = { @@ -560,18 +554,17 @@ static const FcMacRomanFake fcMacRomanFake[] = { static FcChar8 * FcFontCapabilities(FT_Face face); -#define NUM_FC_MAC_ROMAN_FAKE (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0])) +#define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0])) -#if HAVE_ICONV && HAVE_ICONV_H -#define USE_ICONV 1 +#if USE_ICONV #include #endif static FcChar8 * FcSfntNameTranscode (FT_SfntName *sname) { - int i; - char *fromcode; + int i; + const char *fromcode; #if USE_ICONV iconv_t cd; #endif @@ -596,7 +589,7 @@ FcSfntNameTranscode (FT_SfntName *sname) { int f; - fromcode = 0; + fromcode = NULL; for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++) if (fcMacRomanFake[f].language_id == sname->language_id) { @@ -606,36 +599,6 @@ FcSfntNameTranscode (FT_SfntName *sname) if (!fromcode) return 0; } -#if USE_ICONV - cd = iconv_open ("UTF-8", fromcode); - if (cd) - { - size_t in_bytes_left = sname->string_len; - size_t out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN; - char *inbuf, *outbuf; - - utf8 = malloc (out_bytes_left + 1); - if (!utf8) - return 0; - - outbuf = (char *) utf8; - inbuf = (char *) sname->string; - - while (in_bytes_left) - { - size_t did = iconv (cd, - &inbuf, &in_bytes_left, - &outbuf, &out_bytes_left); - if (did == (size_t) (-1)) - { - free (utf8); - return 0; - } - } - *outbuf = '\0'; - goto done; - } -#endif if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE")) { FcChar8 *src = sname->string; @@ -726,9 +689,44 @@ FcSfntNameTranscode (FT_SfntName *sname) *u8 = '\0'; goto done; } +#if USE_ICONV + cd = iconv_open ("UTF-8", fromcode); + if (cd && cd != (iconv_t) (-1)) + { + size_t in_bytes_left = sname->string_len; + size_t out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN; + char *inbuf, *outbuf; + + utf8 = malloc (out_bytes_left + 1); + if (!utf8) + { + iconv_close (cd); + return 0; + } + + outbuf = (char *) utf8; + inbuf = (char *) sname->string; + + while (in_bytes_left) + { + size_t did = iconv (cd, + &inbuf, &in_bytes_left, + &outbuf, &out_bytes_left); + if (did == (size_t) (-1)) + { + iconv_close (cd); + free (utf8); + return 0; + } + } + iconv_close (cd); + *outbuf = '\0'; + goto done; + } +#endif return 0; done: - if (FcStrCmpIgnoreBlanksAndCase (utf8, "") == 0) + if (FcStrCmpIgnoreBlanksAndCase (utf8, (FcChar8 *) "") == 0) { free (utf8); return 0; @@ -736,7 +734,7 @@ done: return utf8; } -static FcChar8 * +static const FcChar8 * FcSfntNameLanguage (FT_SfntName *sname) { int i; @@ -744,7 +742,12 @@ FcSfntNameLanguage (FT_SfntName *sname) if (fcFtLanguage[i].platform_id == sname->platform_id && (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE || fcFtLanguage[i].language_id == sname->language_id)) - return fcFtLanguage[i].lang; + { + if (fcFtLanguage[i].lang[0] == '\0') + return NULL; + else + return (FcChar8 *) fcFtLanguage[i].lang; + } return 0; } @@ -776,7 +779,7 @@ static const struct { (const FcChar8 *) "hanyang" } }; -#define NUM_NOTICE_FOUNDRIES (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0])) +#define NUM_NOTICE_FOUNDRIES (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0])) static const FcChar8 * FcNoticeFoundry(const FT_String *notice) @@ -796,7 +799,7 @@ FcVendorMatch(const FT_Char vendor[4], const FT_Char *vendor_string) /* vendor is not necessarily NUL-terminated. */ int i, len; - len = strlen(vendor_string); + len = strlen((char *) vendor_string); if (memcmp(vendor, vendor_string, len) != 0) return FcFalse; for (i = len; i < 4; i++) @@ -845,7 +848,7 @@ static const struct { { (const FT_Char *) "Y&Y", (const FcChar8 *) "y&y"} }; -#define NUM_VENDOR_FOUNDRIES (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0])) +#define NUM_VENDOR_FOUNDRIES (int) (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0])) static const FcChar8 * FcVendorFoundry(const FT_Char vendor[4]) @@ -890,53 +893,55 @@ FcStringContainsConst (const FcChar8 *string, return -1; } +typedef FcChar8 *FC8; + static const FcStringConst weightConsts[] = { - { "thin", FC_WEIGHT_THIN }, - { "extralight", FC_WEIGHT_EXTRALIGHT }, - { "ultralight", FC_WEIGHT_ULTRALIGHT }, - { "light", FC_WEIGHT_LIGHT }, - { "book", FC_WEIGHT_BOOK }, - { "regular", FC_WEIGHT_REGULAR }, - { "normal", FC_WEIGHT_NORMAL }, - { "medium", FC_WEIGHT_MEDIUM }, - { "demibold", FC_WEIGHT_DEMIBOLD }, - { "demi", FC_WEIGHT_DEMIBOLD }, - { "semibold", FC_WEIGHT_SEMIBOLD }, - { "bold", FC_WEIGHT_BOLD }, - { "extrabold", FC_WEIGHT_EXTRABOLD }, - { "ultrabold", FC_WEIGHT_ULTRABOLD }, - { "black", FC_WEIGHT_BLACK }, - { "heavy", FC_WEIGHT_HEAVY }, + { (FC8) "thin", FC_WEIGHT_THIN }, + { (FC8) "extralight", FC_WEIGHT_EXTRALIGHT }, + { (FC8) "ultralight", FC_WEIGHT_ULTRALIGHT }, + { (FC8) "light", FC_WEIGHT_LIGHT }, + { (FC8) "book", FC_WEIGHT_BOOK }, + { (FC8) "regular", FC_WEIGHT_REGULAR }, + { (FC8) "normal", FC_WEIGHT_NORMAL }, + { (FC8) "medium", FC_WEIGHT_MEDIUM }, + { (FC8) "demibold", FC_WEIGHT_DEMIBOLD }, + { (FC8) "demi", FC_WEIGHT_DEMIBOLD }, + { (FC8) "semibold", FC_WEIGHT_SEMIBOLD }, + { (FC8) "bold", FC_WEIGHT_BOLD }, + { (FC8) "extrabold", FC_WEIGHT_EXTRABOLD }, + { (FC8) "ultrabold", FC_WEIGHT_ULTRABOLD }, + { (FC8) "black", FC_WEIGHT_BLACK }, + { (FC8) "heavy", FC_WEIGHT_HEAVY }, }; -#define NUM_WEIGHT_CONSTS (sizeof (weightConsts) / sizeof (weightConsts[0])) +#define NUM_WEIGHT_CONSTS (int) (sizeof (weightConsts) / sizeof (weightConsts[0])) #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS) #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS) static const FcStringConst widthConsts[] = { - { "ultracondensed", FC_WIDTH_ULTRACONDENSED }, - { "extracondensed", FC_WIDTH_EXTRACONDENSED }, - { "semicondensed", FC_WIDTH_SEMICONDENSED }, - { "condensed", FC_WIDTH_CONDENSED }, /* must be after *condensed */ - { "normal", FC_WIDTH_NORMAL }, - { "semiexpanded", FC_WIDTH_SEMIEXPANDED }, - { "extraexpanded", FC_WIDTH_EXTRAEXPANDED }, - { "ultraexpanded", FC_WIDTH_ULTRAEXPANDED }, - { "expanded", FC_WIDTH_EXPANDED }, /* must be after *expanded */ + { (FC8) "ultracondensed", FC_WIDTH_ULTRACONDENSED }, + { (FC8) "extracondensed", FC_WIDTH_EXTRACONDENSED }, + { (FC8) "semicondensed", FC_WIDTH_SEMICONDENSED }, + { (FC8) "condensed", FC_WIDTH_CONDENSED }, /* must be after *condensed */ + { (FC8) "normal", FC_WIDTH_NORMAL }, + { (FC8) "semiexpanded", FC_WIDTH_SEMIEXPANDED }, + { (FC8) "extraexpanded", FC_WIDTH_EXTRAEXPANDED }, + { (FC8) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED }, + { (FC8) "expanded", FC_WIDTH_EXPANDED }, /* must be after *expanded */ }; -#define NUM_WIDTH_CONSTS (sizeof (widthConsts) / sizeof (widthConsts[0])) +#define NUM_WIDTH_CONSTS (int) (sizeof (widthConsts) / sizeof (widthConsts[0])) #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS) #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS) static const FcStringConst slantConsts[] = { - { "italic", FC_SLANT_ITALIC }, - { "oblique", FC_SLANT_OBLIQUE }, + { (FC8) "italic", FC_SLANT_ITALIC }, + { (FC8) "oblique", FC_SLANT_OBLIQUE }, }; -#define NUM_SLANT_CONSTS (sizeof (slantConsts) / sizeof (slantConsts[0])) +#define NUM_SLANT_CONSTS (int) (sizeof (slantConsts) / sizeof (slantConsts[0])) #define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS) #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS) @@ -950,7 +955,7 @@ FcGetPixelSize (FT_Face face, int i) BDF_PropertyRec prop; int rc; - rc = MY_Get_BDF_Property (face, "PIXEL_SIZE", &prop); + rc = FT_Get_BDF_Property (face, "PIXEL_SIZE", &prop); if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) return (double) prop.u.integer; } @@ -963,7 +968,7 @@ FcGetPixelSize (FT_Face face, int i) } static FcBool -FcStringInPatternElement (FcPattern *pat, char *elt, FcChar8 *string) +FcStringInPatternElement (FcPattern *pat, const char *elt, FcChar8 *string) { int e; FcChar8 *old; @@ -971,7 +976,6 @@ FcStringInPatternElement (FcPattern *pat, char *elt, FcChar8 *string) if (!FcStrCmpIgnoreBlanksAndCase (old, string)) { return FcTrue; - break; } return FcFalse; } @@ -1067,8 +1071,8 @@ FcFreeTypeQuery (const FcChar8 *file, for (snamei = 0; snamei < snamec; snamei++) { FcChar8 *utf8; - FcChar8 *lang; - char *elt = 0, *eltlang = 0; + const FcChar8 *lang; + const char *elt = 0, *eltlang = 0; int *np = 0, *nlangp = 0; if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0) @@ -1149,7 +1153,7 @@ FcFreeTypeQuery (const FcChar8 *file, /* pad lang list with 'xx' to line up with elt */ while (*nlangp < *np) { - if (!FcPatternAddString (pat, eltlang, "xx")) + if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "xx")) goto bail1; ++*nlangp; } @@ -1164,21 +1168,21 @@ FcFreeTypeQuery (const FcChar8 *file, } if (!nfamily && face->family_name && - FcStrCmpIgnoreBlanksAndCase (face->family_name, "") != 0) + FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0) { if (FcDebug () & FC_DBG_SCANV) printf ("using FreeType family \"%s\"\n", face->family_name); - if (!FcPatternAddString (pat, FC_FAMILY, face->family_name)) + if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name)) goto bail1; ++nfamily; } if (!nstyle && face->style_name && - FcStrCmpIgnoreBlanksAndCase (face->style_name, "") != 0) + FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0) { if (FcDebug () & FC_DBG_SCANV) printf ("using FreeType style \"%s\"\n", face->style_name); - if (!FcPatternAddString (pat, FC_STYLE, face->style_name)) + if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name)) goto bail1; ++nstyle; } @@ -1216,7 +1220,7 @@ FcFreeTypeQuery (const FcChar8 *file, * or which are simply a FC_FAMILY and FC_STYLE glued together */ { - int fn, fa, st; + int fn, fa; FcChar8 *full; FcChar8 *fam; FcChar8 *style; @@ -1395,7 +1399,7 @@ FcFreeTypeQuery (const FcChar8 *file, { if (weight == -1 && psfontinfo.weight) { - weight = FcIsWeight (psfontinfo.weight); + weight = FcIsWeight ((FcChar8 *) psfontinfo.weight); if (FcDebug() & FC_DBG_SCANV) printf ("\tType1 weight %s maps to %d\n", psfontinfo.weight, weight); @@ -1426,15 +1430,14 @@ FcFreeTypeQuery (const FcChar8 *file, if (!foundry) { int rc; - BDF_PropertyRec prop; - rc = MY_Get_BDF_Property(face, "FOUNDRY", &prop); + rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop); if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) - foundry = prop.u.atom; + foundry = (FcChar8 *) prop.u.atom; } if (width == -1) { - if (MY_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 && + if (FT_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 && (prop.type == BDF_PROPERTY_TYPE_INTEGER || prop.type == BDF_PROPERTY_TYPE_CARDINAL)) { @@ -1457,10 +1460,10 @@ FcFreeTypeQuery (const FcChar8 *file, } } if (width == -1 && - MY_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 && + FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { - width = FcIsWidth (prop.u.atom); + width = FcIsWidth ((FcChar8 *) prop.u.atom); if (FcDebug () & FC_DBG_SCANV) printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width); } @@ -1513,7 +1516,7 @@ FcFreeTypeQuery (const FcChar8 *file, width = FC_WIDTH_NORMAL; if (foundry == 0) - foundry = "unknown"; + foundry = (FcChar8 *) "unknown"; if (!FcPatternAddInteger (pat, FC_SLANT, slant)) goto bail1; @@ -1537,7 +1540,7 @@ FcFreeTypeQuery (const FcChar8 *file, #if HAVE_FT_GET_BDF_PROPERTY /* For PCF fonts, override the computed spacing with the one from the property */ - if(MY_Get_BDF_Property(face, "SPACING", &prop) == 0 && + if(FT_Get_BDF_Property(face, "SPACING", &prop) == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C")) spacing = FC_CHARCELL; @@ -1551,11 +1554,16 @@ FcFreeTypeQuery (const FcChar8 *file, /* * Skip over PCF fonts that have no encoded characters; they're * usually just Unicode fonts transcoded to some legacy encoding + * ftglue.c forces us to approximate whether a font is a PCF font + * or not by whether it has any BDF properties. Try PIXEL_SIZE; + * I don't know how to get a list of BDF properties on the font. -PL */ if (FcCharSetCount (cs) == 0) { - if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf")) +#if HAVE_FT_GET_BDF_PROPERTY + if(FT_Get_BDF_Property(face, "PIXEL_SIZE", &prop) == 0) goto bail2; +#endif } if (!FcPatternAddCharSet (pat, FC_CHARSET, cs)) @@ -1582,16 +1590,20 @@ FcFreeTypeQuery (const FcChar8 *file, for (i = 0; i < face->num_fixed_sizes; i++) if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE, FcGetPixelSize (face, i))) - goto bail1; + goto bail2; if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse)) - goto bail1; + goto bail2; #if HAVE_FT_GET_BDF_PROPERTY if(face->num_fixed_sizes == 1) { int rc; int value; - BDF_PropertyRec prop; - rc = MY_Get_BDF_Property(face, "POINT_SIZE", &prop); + /* skip bitmap fonts which do not even have a family name */ + rc = FT_Get_BDF_Property(face, "FAMILY_NAME", &prop); + if (rc != 0 || prop.type != BDF_PROPERTY_TYPE_ATOM) + goto bail2; + + rc = FT_Get_BDF_Property(face, "POINT_SIZE", &prop); if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) value = prop.u.integer; else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL) @@ -1601,7 +1613,7 @@ FcFreeTypeQuery (const FcChar8 *file, if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0)) goto nevermind; - rc = MY_Get_BDF_Property(face, "RESOLUTION_Y", &prop); + rc = FT_Get_BDF_Property(face, "RESOLUTION_Y", &prop); if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) value = prop.u.integer; else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL) @@ -1624,7 +1636,7 @@ FcFreeTypeQuery (const FcChar8 *file, { const char *font_format = FT_Get_X11_Font_Format (face); if (font_format) - FcPatternAddString (pat, FC_FONTFORMAT, font_format); + FcPatternAddString (pat, FC_FONTFORMAT, (FcChar8 *) font_format); } #endif @@ -2118,7 +2130,13 @@ static const FcFontDecode fcFontDecoders[] = { { ft_encoding_apple_roman, &AppleRoman, (1 << 16) - 1 }, }; -#define NUM_DECODE (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0])) +#define NUM_DECODE (int) (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0])) + +static const FcChar32 prefer_unicode[] = { + 0x20ac, /* EURO SIGN */ +}; + +#define NUM_PREFER_UNICODE (int) (sizeof (prefer_unicode) / sizeof (prefer_unicode[0])) FcChar32 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map) @@ -2199,12 +2217,12 @@ FcFreeTypeUseNames (FT_Face face) return FcFalse; } -static FcChar8 * +static const FcChar8 * FcUcs4ToGlyphName (FcChar32 ucs4) { int i = (int) (ucs4 % FC_GLYPHNAME_HASH); int r = 0; - FcGlyphName *gn; + const FcGlyphName *gn; while ((gn = ucs_to_name[i])) { @@ -2229,7 +2247,7 @@ FcGlyphNameToUcs4 (FcChar8 *name) FcChar32 h = FcHashGlyphName (name); int i = (int) (h % FC_GLYPHNAME_HASH); int r = 0; - FcGlyphName *gn; + const FcGlyphName *gn; while ((gn = name_to_ucs[i])) { @@ -2254,12 +2272,12 @@ FcGlyphNameToUcs4 (FcChar8 *name) * any defined order within the font */ static FT_UInt -FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name) +FcFreeTypeGlyphNameIndex (FT_Face face, const FcChar8 *name) { FT_UInt gindex; FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2]; - for (gindex = 0; gindex < face->num_glyphs; gindex++) + for (gindex = 0; gindex < (FT_UInt) face->num_glyphs; gindex++) { if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0) if (!strcmp ((char *) name, (char *) name_buf)) @@ -2281,8 +2299,13 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) int initial, offset, decode; FT_UInt glyphindex; FcChar32 charcode; + int p; initial = 0; + + if (!face) + return 0; + /* * Find the current encoding */ @@ -2294,6 +2317,12 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) if (initial == NUM_DECODE) initial = 0; } + for (p = 0; p < NUM_PREFER_UNICODE; p++) + if (ucs4 == prefer_unicode[p]) + { + initial = 0; + break; + } /* * Check each encoding for the glyph, starting with the current one */ @@ -2306,7 +2335,7 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) if (fcFontDecoders[decode].map) { charcode = FcFreeTypeUcs4ToPrivate (ucs4, fcFontDecoders[decode].map); - if (charcode == ~0) + if (charcode == ~0U) continue; } else @@ -2321,7 +2350,7 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) */ if (FcFreeTypeUseNames (face)) { - FcChar8 *name = FcUcs4ToGlyphName (ucs4); + const FcChar8 *name = FcUcs4ToGlyphName (ucs4); if (name) { glyphindex = FcFreeTypeGlyphNameIndex (face, name); @@ -2341,12 +2370,6 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; FT_GlyphSlot slot; - /* - * For bitmap-only fonts, assume that they're OK. - */ - if ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) - return FcTrue; - /* * When using scalable fonts, only report those glyphs * which can be scaled; otherwise those fonts will @@ -2403,7 +2426,7 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, FcCharSet * FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) { - FcChar32 page, off, max, ucs4; + FcChar32 page, off, ucs4; #ifdef CHECK FcChar32 font_max = 0; #endif @@ -2441,22 +2464,33 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) if (glyph && FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) { - if (!has_advance) + /* + * ignore glyphs with zero advance. They’re + * combining characters, and while their behaviour + * isn’t well defined for monospaced applications in + * Unicode, there are many fonts which include + * zero-width combining characters in otherwise + * monospaced fonts. + */ + if (advance) { - has_advance = FcTrue; - advance_one = advance; + if (!has_advance) + { + has_advance = FcTrue; + advance_one = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_one)) + { + if (fixed_advance) + { + dual_advance = FcTrue; + fixed_advance = FcFalse; + advance_two = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_two)) + dual_advance = FcFalse; + } } - else if (!APPROXIMATELY_EQUAL (advance, advance_one)) - { - if (fixed_advance) - { - dual_advance = FcTrue; - fixed_advance = FcFalse; - advance_two = advance; - } - else if (!APPROXIMATELY_EQUAL (advance, advance_two)) - dual_advance = FcFalse; - } leaf = FcCharSetFindLeafCreate (fcs, ucs4); if (!leaf) @@ -2473,7 +2507,6 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) { FT_UInt gindex; - max = fcFontDecoders[o].max; /* * Find the first encoded character in the font */ @@ -2499,22 +2532,25 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) if (glyph && FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) { - if (!has_advance) + if (advance) { - has_advance = FcTrue; - advance_one = advance; + if (!has_advance) + { + has_advance = FcTrue; + advance_one = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_one)) + { + if (fixed_advance) + { + dual_advance = FcTrue; + fixed_advance = FcFalse; + advance_two = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_two)) + dual_advance = FcFalse; + } } - else if (!APPROXIMATELY_EQUAL (advance, advance_one)) - { - if (fixed_advance) - { - dual_advance = FcTrue; - fixed_advance = FcFalse; - advance_two = advance; - } - else if (!APPROXIMATELY_EQUAL (advance, advance_two)) - dual_advance = FcFalse; - } if (!leaf) { @@ -2558,7 +2594,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) { FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2]; - for (glyph = 0; glyph < face->num_glyphs; glyph++) + for (glyph = 0; glyph < (FT_UInt) face->num_glyphs; glyph++) { if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0) { @@ -2566,22 +2602,25 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) if (ucs4 != 0xffff && FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) { - if (!has_advance) + if (advance) { - has_advance = FcTrue; - advance_one = advance; + if (!has_advance) + { + has_advance = FcTrue; + advance_one = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_one)) + { + if (fixed_advance) + { + dual_advance = FcTrue; + fixed_advance = FcFalse; + advance_two = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_two)) + dual_advance = FcFalse; + } } - else if (!APPROXIMATELY_EQUAL (advance, advance_one)) - { - if (fixed_advance) - { - dual_advance = FcTrue; - fixed_advance = FcFalse; - advance_two = advance; - } - else if (!APPROXIMATELY_EQUAL (advance, advance_two)) - dual_advance = FcFalse; - } leaf = FcCharSetFindLeafCreate (fcs, ucs4); if (!leaf) goto bail1; @@ -2643,17 +2682,43 @@ FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks) #define TTO_Err_Empty_Script 0x1005 #define TTO_Err_Invalid_SubTable 0x1001 +#define OTLAYOUT_HEAD "otlayout:" +#define OTLAYOUT_HEAD_LEN 9 +#define OTLAYOUT_ID_LEN 4 +/* space + head + id */ +#define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN) +/* + * This is a bit generous; the registry has only lower case and space + * except for 'DFLT'. + */ +#define FcIsSpace(x) (040 == (x)) +#define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x)) + static void addtag(FcChar8 *complex, FT_ULong tag) { - FcChar8 tagstring[15]; - sprintf (tagstring, "otlayout:%c%c%c%c ", - (unsigned char)(tag >> 24), - (unsigned char)((tag & 0xff0000) >> 16), - (unsigned char)((tag & 0xff00) >> 8), - (unsigned char)(tag & 0xff)); - strncat(complex, tagstring, 14); + FcChar8 tagstring[OTLAYOUT_ID_LEN + 1]; + + tagstring[0] = (FcChar8)(tag >> 24), + tagstring[1] = (FcChar8)(tag >> 16), + tagstring[2] = (FcChar8)(tag >> 8), + tagstring[3] = (FcChar8)(tag); + tagstring[4] = '\0'; + + /* skip tags which aren't alphabetic, under the assumption that + * they're probably broken + */ + if (!FcIsValidScript(tagstring[0]) || + !FcIsValidScript(tagstring[1]) || + !FcIsValidScript(tagstring[2]) || + !FcIsValidScript(tagstring[3])) + return; + + if (*complex != '\0') + strcat ((char *) complex, " "); + strcat ((char *) complex, "otlayout:"); + strcat ((char *) complex, (char *) tagstring); } static int @@ -2669,68 +2734,68 @@ static FT_Error GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags, FT_UShort *script_count) { FT_ULong cur_offset, new_offset, base_offset; - TT_Face tt_face = (TT_Face)face; FT_Stream stream = face->stream; FT_Error error; FT_UShort n, p; - FT_Memory memory = stream->memory; + FT_Memory memory; if ( !stream ) return TT_Err_Invalid_Face_Handle; - if (( error = tt_face->goto_table( tt_face, tabletag, stream, 0 ) )) + memory = stream->memory; + + if (( error = ftglue_face_goto_table( face, tabletag, stream ) )) return error; - base_offset = FT_STREAM_POS(); + base_offset = ftglue_stream_pos ( stream ); /* skip version */ - if ( FT_STREAM_SEEK( base_offset + 4L ) || FT_FRAME_ENTER( 2L ) ) + if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) ) return error; - new_offset = FT_GET_USHORT() + base_offset; + new_offset = GET_UShort() + base_offset; - FT_FRAME_EXIT(); + ftglue_stream_frame_exit( stream ); - cur_offset = FT_STREAM_POS(); + cur_offset = ftglue_stream_pos( stream ); - if ( FT_STREAM_SEEK( new_offset ) != TT_Err_Ok ) + if ( ftglue_stream_seek( stream, new_offset ) != TT_Err_Ok ) return error; - base_offset = FT_STREAM_POS(); + base_offset = ftglue_stream_pos( stream ); - if ( FT_FRAME_ENTER( 2L ) ) + if ( ftglue_stream_frame_enter( stream, 2L ) ) return error; - *script_count = FT_GET_USHORT(); + *script_count = GET_UShort (); + + ftglue_stream_frame_exit( stream ); - FT_FRAME_EXIT(); + *stags = ftglue_alloc(memory, *script_count * sizeof( FT_ULong ), &error); - if ( FT_SET_ERROR (FT_MEM_ALLOC_ARRAY( *stags, *script_count, FT_ULong )) ) + if (error) return error; p = 0; for ( n = 0; n < *script_count; n++ ) { - if ( FT_FRAME_ENTER( 6L ) ) + if ( ftglue_stream_frame_enter( stream, 6L ) ) goto Fail; - (*stags)[p] = FT_GET_ULONG(); - new_offset = FT_GET_USHORT() + base_offset; + (*stags)[p] = GET_ULong (); + new_offset = GET_UShort () + base_offset; - FT_FRAME_EXIT(); + ftglue_stream_frame_exit( stream ); - cur_offset = FT_STREAM_POS(); + cur_offset = ftglue_stream_pos( stream ); - if ( FT_STREAM_SEEK( new_offset ) ) - goto Fail; + error = ftglue_stream_seek( stream, new_offset ); if ( error == TT_Err_Ok ) p++; - else if ( error != TTO_Err_Empty_Script ) - goto Fail; - (void)FT_STREAM_SEEK( cur_offset ); + (void)ftglue_stream_seek( stream, cur_offset ); } if (!p) @@ -2739,13 +2804,15 @@ GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags, FT_UShort *scri goto Fail; } - // sort the tag list before returning it + /* sort the tag list before returning it */ qsort(*stags, *script_count, sizeof(FT_ULong), compareulong); return TT_Err_Ok; Fail: - FT_FREE( *stags ); + *script_count = 0; + ftglue_free( memory, *stags ); + *stags = NULL; return error; } @@ -2756,7 +2823,8 @@ FcFontCapabilities(FT_Face face) FT_Error err; FT_ULong len = 0; FT_ULong *gsubtags=NULL, *gpostags=NULL; - FT_UShort gsub_count=0, gpos_count=0, maxsize; + FT_UShort gsub_count=0, gpos_count=0; + FT_ULong maxsize; FT_Memory memory = face->stream->memory; FcChar8 *complex = NULL; int indx1 = 0, indx2 = 0; @@ -2764,23 +2832,23 @@ FcFontCapabilities(FT_Face face) err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len); issilgraphitefont = ( err == FT_Err_Ok); - err = GetScriptTags(face, TTAG_GPOS, &gpostags, &gpos_count); - err = GetScriptTags(face, TTAG_GSUB, &gsubtags, &gsub_count); + if (GetScriptTags(face, TTAG_GPOS, &gpostags, &gpos_count) != FT_Err_Ok) + gpos_count = 0; + if (GetScriptTags(face, TTAG_GSUB, &gsubtags, &gsub_count) != FT_Err_Ok) + gsub_count = 0; + if (!issilgraphitefont && !gsub_count && !gpos_count) - { goto bail; - } - maxsize = ((gpos_count + gsub_count) * 15) + (issilgraphitefont ? 13 : 0); + maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN + + (issilgraphitefont ? 13 : 0)); complex = malloc (sizeof (FcChar8) * maxsize); + if (!complex) + goto bail; + + complex[0] = '\0'; if (issilgraphitefont) - { - strcpy(complex, "ttable:Silf "); - } - else - { - strcpy(complex, ""); - } + strcpy((char *) complex, "ttable:Silf "); while ((indx1 < gsub_count) || (indx2 < gpos_count)) { if (indx1 == gsub_count) { @@ -2801,7 +2869,7 @@ FcFontCapabilities(FT_Face face) if (FcDebug () & FC_DBG_SCANV) printf("complex features in this font: %s\n", complex); bail: - FT_FREE(gsubtags); - FT_FREE(gpostags); + ftglue_free(memory, gsubtags); + ftglue_free(memory, gpostags); return complex; }