X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffcfreetype.c;h=c30826e52549264ebe7161400ddc4842d0468be0;hb=6b1fc678ca59df3f3f1ffac0e509cf485c9df0c0;hp=ee4af405644f847d25c191febe537831496e5642;hpb=716ac8b8033794e2557ad567005dfff4dd95f031;p=fontconfig.git diff --git a/src/fcfreetype.c b/src/fcfreetype.c index ee4af40..c30826e 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -1,5 +1,5 @@ /* - * $RCSId: xc/lib/fontconfig/src/fcfreetype.c,v 1.11 2002/08/31 22:17:32 keithp Exp $ + * fontconfig/src/fcfreetype.c * * Copyright © 2001 Keith Packard * @@ -13,9 +13,9 @@ * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR @@ -44,34 +44,28 @@ THE SOFTWARE. */ +#include "fcint.h" +#include "fcftint.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 +73,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 @@ -86,16 +81,16 @@ */ static const struct { - int bit; - const FcChar8 *lang; + char bit; + const FcChar8 lang[6]; } FcCodePageRange[] = { - { 17, (const FcChar8 *) "ja" }, - { 18, (const FcChar8 *) "zh-cn" }, - { 19, (const FcChar8 *) "ko" }, - { 20, (const FcChar8 *) "zh-tw" }, + { 17, "ja" }, + { 18, "zh-cn" }, + { 19, "ko" }, + { 20, "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 +99,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 @@ -125,28 +120,28 @@ static const FcFtEncoding fcFtEncoding[] = { { TT_PLATFORM_MACINTOSH, TT_MAC_ID_JAPANESE, "SJIS" }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, "UTF-16BE" }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, "SJIS-WIN" }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, "GB3212" }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, "GB2312" }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, "BIG-5" }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, "Wansung" }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, "Johab" }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, "UCS4" }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, "UCS-2BE" }, { TT_PLATFORM_ISO, TT_ISO_ID_7BIT_ASCII, "ASCII" }, { TT_PLATFORM_ISO, TT_ISO_ID_10646, "UCS-2BE" }, { 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 +540,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 +555,39 @@ 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 +/* + * A shift-JIS will have many high bits turned on + */ +static FcBool +FcLooksLikeSJIS (FcChar8 *string, int len) +{ + int nhigh = 0, nlow = 0; + + while (len-- > 0) + { + if (*string++ & 0x80) nhigh++; + else nlow++; + } + /* + * Heuristic -- if more than 1/3 of the bytes have the high-bit set, + * this is likely to be SJIS and not ROMAN + */ + if (nhigh * 2 > nlow) + return FcTrue; + return FcFalse; +} + static FcChar8 * FcSfntNameTranscode (FT_SfntName *sname) { - int i; - char *fromcode; + int i; + const char *fromcode; #if USE_ICONV iconv_t cd; #endif @@ -587,24 +603,35 @@ FcSfntNameTranscode (FT_SfntName *sname) fromcode = fcFtEncoding[i].fromcode; /* - * "real" Mac language IDs are all less than 150. - * Names using one of the MS language IDs are assumed - * to use an associated encoding (Yes, this is a kludge) + * Many names encoded for TT_PLATFORM_MACINTOSH are broken + * in various ways. Kludge around them. */ - if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN) && - sname->language_id >= 0x100) + if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN)) { - int f; + if (sname->language_id == TT_MAC_LANGID_ENGLISH && + FcLooksLikeSJIS (sname->string, sname->string_len)) + { + fromcode = "SJIS"; + } + else if (sname->language_id >= 0x100) + { + /* + * "real" Mac language IDs are all less than 150. + * Names using one of the MS language IDs are assumed + * to use an associated encoding (Yes, this is a kludge) + */ + int f; - fromcode = 0; - for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++) - if (fcMacRomanFake[f].language_id == sname->language_id) - { - fromcode = fcMacRomanFake[f].fromcode; - break; - } - if (!fromcode) - return 0; + fromcode = NULL; + for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++) + if (fcMacRomanFake[f].language_id == sname->language_id) + { + fromcode = fcMacRomanFake[f].fromcode; + break; + } + if (!fromcode) + return 0; + } } if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE")) { @@ -733,7 +760,7 @@ FcSfntNameTranscode (FT_SfntName *sname) #endif return 0; done: - if (FcStrCmpIgnoreBlanksAndCase (utf8, "") == 0) + if (FcStrCmpIgnoreBlanksAndCase (utf8, (FcChar8 *) "") == 0) { free (utf8); return 0; @@ -741,47 +768,84 @@ done: return utf8; } -static FcChar8 * +static const FcChar8 * FcSfntNameLanguage (FT_SfntName *sname) { int i; + FT_UShort platform_id = sname->platform_id; + FT_UShort language_id = sname->language_id; + + /* + * Many names encoded for TT_PLATFORM_MACINTOSH are broken + * in various ways. Kludge around them. + */ + if (platform_id == TT_PLATFORM_MACINTOSH && + sname->encoding_id == TT_MAC_ID_ROMAN && + FcLooksLikeSJIS (sname->string, sname->string_len)) + { + language_id = TT_MAC_LANGID_JAPANESE; + } + for (i = 0; i < NUM_FC_FT_LANGUAGE; i++) - if (fcFtLanguage[i].platform_id == sname->platform_id && + if (fcFtLanguage[i].platform_id == platform_id && (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE || - fcFtLanguage[i].language_id == sname->language_id)) - return fcFtLanguage[i].lang; + fcFtLanguage[i].language_id == language_id)) + { + if (fcFtLanguage[i].lang[0] == '\0') + return NULL; + else + return (FcChar8 *) fcFtLanguage[i].lang; + } return 0; } /* Order is significant. For example, some B&H fonts are hinted by URW++, and both strings appear in the notice. */ -static const struct { - const FT_String *notice; - const FcChar8 *foundry; -} FcNoticeFoundries[] = { - { (const FT_String *) "Bigelow", (const FcChar8 *) "b&h" }, - { (const FT_String *) "Adobe", (const FcChar8 *) "adobe" }, - { (const FT_String *) "Bitstream", (const FcChar8 *) "bitstream" }, - { (const FT_String *) "Monotype", (const FcChar8 *) "monotype" }, - { (const FT_String *) "Linotype", (const FcChar8 *) "linotype" }, - { (const FT_String *) "LINOTYPE-HELL", - (const FcChar8 *) "linotype" }, - { (const FT_String *) "IBM", (const FcChar8 *) "ibm" }, - { (const FT_String *) "URW", (const FcChar8 *) "urw" }, - { (const FT_String *) "International Typeface Corporation", - (const FcChar8 *) "itc" }, - { (const FT_String *) "Tiro Typeworks", - (const FcChar8 *) "tiro" }, - { (const FT_String *) "XFree86", (const FcChar8 *) "xfree86" }, - { (const FT_String *) "Microsoft", (const FcChar8 *) "microsoft" }, - { (const FT_String *) "Omega", (const FcChar8 *) "omega" }, - { (const FT_String *) "Font21", (const FcChar8 *) "hwan" }, - { (const FT_String *) "HanYang System", - (const FcChar8 *) "hanyang" } +static const char notice_foundry_data[] = + "Bigelow\0b&h\0" + "Adobe\0adobe\0" + "Bitstream\0bitstream\0" + "Monotype\0monotype\0" + "Linotype\0linotype\0" + "LINOTYPE-HELL\0linotype\0" + "IBM\0ibm\0" + "URW\0urw\0" + "International Typeface Corporation\0itc\0" + "Tiro Typeworks\0tiro\0" + "XFree86\0xfree86\0" + "Microsoft\0microsoft\0" + "Omega\0omega\0" + "Font21\0hwan\0" + "HanYang System\0hanyang"; + +struct _notice_foundry { + /* these are the offsets into the + * notice_foundry_data array. + */ + unsigned char notice_offset; + unsigned char foundry_offset; +}; + +static const struct _notice_foundry FcNoticeFoundries[] = { + { 0, 8 }, + { 12, 18 }, + { 24, 34 }, + { 44, 53 }, + { 62, 71 }, + { 80, 94 }, + { 103, 107 }, + { 111, 115 }, + { 119, 154 }, + { 158, 173 }, + { 178, 186 }, + { 194, 204 }, + { 214, 220 }, + { 226, 233 }, + { 238, 253 } }; -#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) @@ -790,8 +854,14 @@ FcNoticeFoundry(const FT_String *notice) if (notice) for(i = 0; i < NUM_NOTICE_FOUNDRIES; i++) - if (strstr ((const char *) notice, (const char *) FcNoticeFoundries[i].notice)) - return FcNoticeFoundries[i].foundry; + { + const struct _notice_foundry *nf = &FcNoticeFoundries[i]; + const char *n = notice_foundry_data + nf->notice_offset; + const char *f = notice_foundry_data + nf->foundry_offset; + + if (strstr ((const char *) notice, n)) + return (const FcChar8 *) f; + } return 0; } @@ -801,7 +871,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++) @@ -816,41 +886,41 @@ FcVendorMatch(const FT_Char vendor[4], const FT_Char *vendor_string) entries for padding both with spaces and NULs. */ static const struct { - const FT_Char *vendor; - const FcChar8 *foundry; + const FT_Char vendor[5]; + const FcChar8 foundry[13]; } FcVendorFoundries[] = { - { (const FT_Char *) "ADBE", (const FcChar8 *) "adobe"}, - { (const FT_Char *) "AGFA", (const FcChar8 *) "agfa"}, - { (const FT_Char *) "ALTS", (const FcChar8 *) "altsys"}, - { (const FT_Char *) "APPL", (const FcChar8 *) "apple"}, - { (const FT_Char *) "ARPH", (const FcChar8 *) "arphic"}, - { (const FT_Char *) "ATEC", (const FcChar8 *) "alltype"}, - { (const FT_Char *) "B&H", (const FcChar8 *) "b&h"}, - { (const FT_Char *) "BITS", (const FcChar8 *) "bitstream"}, - { (const FT_Char *) "CANO", (const FcChar8 *) "cannon"}, - { (const FT_Char *) "DYNA", (const FcChar8 *) "dynalab"}, - { (const FT_Char *) "EPSN", (const FcChar8 *) "epson"}, - { (const FT_Char *) "FJ", (const FcChar8 *) "fujitsu"}, - { (const FT_Char *) "IBM", (const FcChar8 *) "ibm"}, - { (const FT_Char *) "ITC", (const FcChar8 *) "itc"}, - { (const FT_Char *) "IMPR", (const FcChar8 *) "impress"}, - { (const FT_Char *) "LARA", (const FcChar8 *) "larabiefonts"}, - { (const FT_Char *) "LEAF", (const FcChar8 *) "interleaf"}, - { (const FT_Char *) "LETR", (const FcChar8 *) "letraset"}, - { (const FT_Char *) "LINO", (const FcChar8 *) "linotype"}, - { (const FT_Char *) "MACR", (const FcChar8 *) "macromedia"}, - { (const FT_Char *) "MONO", (const FcChar8 *) "monotype"}, - { (const FT_Char *) "MS", (const FcChar8 *) "microsoft"}, - { (const FT_Char *) "MT", (const FcChar8 *) "monotype"}, - { (const FT_Char *) "NEC", (const FcChar8 *) "nec"}, - { (const FT_Char *) "PARA", (const FcChar8 *) "paratype"}, - { (const FT_Char *) "QMSI", (const FcChar8 *) "qms"}, - { (const FT_Char *) "RICO", (const FcChar8 *) "ricoh"}, - { (const FT_Char *) "URW", (const FcChar8 *) "urw"}, - { (const FT_Char *) "Y&Y", (const FcChar8 *) "y&y"} + { "ADBE", "adobe"}, + { "AGFA", "agfa"}, + { "ALTS", "altsys"}, + { "APPL", "apple"}, + { "ARPH", "arphic"}, + { "ATEC", "alltype"}, + { "B&H", "b&h"}, + { "BITS", "bitstream"}, + { "CANO", "cannon"}, + { "DYNA", "dynalab"}, + { "EPSN", "epson"}, + { "FJ", "fujitsu"}, + { "IBM", "ibm"}, + { "ITC", "itc"}, + { "IMPR", "impress"}, + { "LARA", "larabiefonts"}, + { "LEAF", "interleaf"}, + { "LETR", "letraset"}, + { "LINO", "linotype"}, + { "MACR", "macromedia"}, + { "MONO", "monotype"}, + { "MS", "microsoft"}, + { "MT", "monotype"}, + { "NEC", "nec"}, + { "PARA", "paratype"}, + { "QMSI", "qms"}, + { "RICO", "ricoh"}, + { "URW", "urw"}, + { "Y&Y", "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,62 +960,95 @@ FcStringContainsConst (const FcChar8 *string, int i; for (i = 0; i < nc; i++) - if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name)) - return c[i].value; + { + if (c[i].name[0] == '<') + { + if (FcStrContainsWord (string, c[i].name + 1)) + return c[i].value; + } + else + { + if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name)) + return c[i].value; + } + } 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) "extrabold", FC_WEIGHT_EXTRABOLD }, + { (FC8) "superbold", FC_WEIGHT_EXTRABOLD }, + { (FC8) "ultrabold", FC_WEIGHT_ULTRABOLD }, + { (FC8) "bold", FC_WEIGHT_BOLD }, + { (FC8) "ultrablack", FC_WEIGHT_ULTRABLACK }, + { (FC8) "superblack", FC_WEIGHT_EXTRABLACK }, + { (FC8) "extrablack", FC_WEIGHT_EXTRABLACK }, + { (FC8) "num_faces; - pat = FcPatternCreate (); if (!pat) goto bail0; @@ -1069,121 +1189,167 @@ FcFreeTypeQuery (const FcChar8 *file, * of them */ snamec = FT_Get_Sfnt_Name_Count (face); - for (snamei = 0; snamei < snamec; snamei++) + for (p = 0; p <= NUM_PLATFORM_ORDER; p++) { - FcChar8 *utf8; - FcChar8 *lang; - char *elt = 0, *eltlang = 0; - int *np = 0, *nlangp = 0; - - if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0) - continue; - - utf8 = FcSfntNameTranscode (&sname); - lang = FcSfntNameLanguage (&sname); + if (p < NUM_PLATFORM_ORDER) + platform = platform_order[p]; + else + platform = 0xffff; - if (!utf8) - continue; - - switch (sname.name_id) { - case TT_NAME_ID_FONT_FAMILY: -#if 0 - case TT_NAME_ID_PS_NAME: - case TT_NAME_ID_UNIQUE_ID: -#endif - if (FcDebug () & FC_DBG_SCANV) - printf ("found family (n %2d p %d e %d l 0x%04x) %s\n", - sname.name_id, sname.platform_id, - sname.encoding_id, sname.language_id, - utf8); - - elt = FC_FAMILY; - eltlang = FC_FAMILYLANG; - np = &nfamily; - nlangp = &nfamily_lang; - break; - case TT_NAME_ID_FULL_NAME: - case TT_NAME_ID_MAC_FULL_NAME: - if (FcDebug () & FC_DBG_SCANV) - printf ("found full (n %2d p %d e %d l 0x%04x) %s\n", - sname.name_id, sname.platform_id, - sname.encoding_id, sname.language_id, - utf8); - - elt = FC_FULLNAME; - eltlang = FC_FULLNAMELANG; - np = &nfullname; - nlangp = &nfullname_lang; - break; - case TT_NAME_ID_FONT_SUBFAMILY: - if (FcDebug () & FC_DBG_SCANV) - printf ("found style (n %2d p %d e %d l 0x%04x) %s\n", - sname.name_id, sname.platform_id, - sname.encoding_id, sname.language_id, - utf8); - - elt = FC_STYLE; - eltlang = FC_STYLELANG; - np = &nstyle; - nlangp = &nstyle_lang; - break; - case TT_NAME_ID_TRADEMARK: - case TT_NAME_ID_MANUFACTURER: - /* If the foundry wasn't found in the OS/2 table, look here */ - if(!foundry) - foundry = FcNoticeFoundry((FT_String *) utf8); - break; - } - if (elt) + /* + * Order nameids so preferred names appear first + * in the resulting list + */ + for (n = 0; n < NUM_NAMEID_ORDER; n++) { - if (FcStringInPatternElement (pat, elt, utf8)) - { - free (utf8); - continue; - } + nameid = nameid_order[n]; - /* add new element */ - if (!FcPatternAddString (pat, elt, utf8)) - { - free (utf8); - goto bail1; - } - free (utf8); - if (lang) + for (snamei = 0; snamei < snamec; snamei++) { - /* pad lang list with 'xx' to line up with elt */ - while (*nlangp < *np) + FcChar8 *utf8; + const FcChar8 *lang; + const char *elt = 0, *eltlang = 0; + int *np = 0, *nlangp = 0; + + if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0) + continue; + if (sname.name_id != nameid) + continue; + + /* + * Sort platforms in preference order, accepting + * all other platforms last + */ + if (p < NUM_PLATFORM_ORDER) + { + if (sname.platform_id != platform) + continue; + } + else + { + int sp; + + for (sp = 0; sp < NUM_PLATFORM_ORDER; sp++) + if (sname.platform_id == platform_order[sp]) + break; + if (sp != NUM_PLATFORM_ORDER) + continue; + } + utf8 = FcSfntNameTranscode (&sname); + lang = FcSfntNameLanguage (&sname); + + if (!utf8) + continue; + + switch (sname.name_id) { +#ifdef TT_NAME_ID_WWS_FAMILY + case TT_NAME_ID_WWS_FAMILY: +#endif + case TT_NAME_ID_PREFERRED_FAMILY: + case TT_NAME_ID_FONT_FAMILY: +#if 0 + case TT_NAME_ID_PS_NAME: + case TT_NAME_ID_UNIQUE_ID: +#endif + if (FcDebug () & FC_DBG_SCANV) + printf ("found family (n %2d p %d e %d l 0x%04x) %s\n", + sname.name_id, sname.platform_id, + sname.encoding_id, sname.language_id, + utf8); + + elt = FC_FAMILY; + eltlang = FC_FAMILYLANG; + np = &nfamily; + nlangp = &nfamily_lang; + break; + case TT_NAME_ID_MAC_FULL_NAME: + case TT_NAME_ID_FULL_NAME: + if (FcDebug () & FC_DBG_SCANV) + printf ("found full (n %2d p %d e %d l 0x%04x) %s\n", + sname.name_id, sname.platform_id, + sname.encoding_id, sname.language_id, + utf8); + + elt = FC_FULLNAME; + eltlang = FC_FULLNAMELANG; + np = &nfullname; + nlangp = &nfullname_lang; + break; +#ifdef TT_NAME_ID_WWS_SUBFAMILY + case TT_NAME_ID_WWS_SUBFAMILY: +#endif + case TT_NAME_ID_PREFERRED_SUBFAMILY: + case TT_NAME_ID_FONT_SUBFAMILY: + if (FcDebug () & FC_DBG_SCANV) + printf ("found style (n %2d p %d e %d l 0x%04x) %s\n", + sname.name_id, sname.platform_id, + sname.encoding_id, sname.language_id, + utf8); + + elt = FC_STYLE; + eltlang = FC_STYLELANG; + np = &nstyle; + nlangp = &nstyle_lang; + break; + case TT_NAME_ID_TRADEMARK: + case TT_NAME_ID_MANUFACTURER: + /* If the foundry wasn't found in the OS/2 table, look here */ + if(!foundry) + foundry = FcNoticeFoundry((FT_String *) utf8); + break; + } + if (elt) { - if (!FcPatternAddString (pat, eltlang, "xx")) + if (FcStringInPatternElement (pat, elt, utf8)) + { + free (utf8); + continue; + } + + /* add new element */ + if (!FcPatternAddString (pat, elt, utf8)) + { + free (utf8); goto bail1; - ++*nlangp; + } + free (utf8); + if (lang) + { + /* pad lang list with 'xx' to line up with elt */ + while (*nlangp < *np) + { + if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "xx")) + goto bail1; + ++*nlangp; + } + if (!FcPatternAddString (pat, eltlang, lang)) + goto bail1; + ++*nlangp; + } + ++*np; } - if (!FcPatternAddString (pat, eltlang, lang)) - goto bail1; - ++*nlangp; + else + free (utf8); } - ++*np; } - else - free (utf8); } - + 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,70 +1382,6 @@ FcFreeTypeQuery (const FcChar8 *file, ++nfamily; } - /* - * Walk through FC_FULLNAME entries eliding those in FC_FAMILY - * or which are simply a FC_FAMILY and FC_STYLE glued together - */ - { - int fn, fa, st; - FcChar8 *full; - FcChar8 *fam; - FcChar8 *style; - - for (fn = 0; FcPatternGetString (pat, FC_FULLNAME, fn, &full) == FcResultMatch; fn++) - { - FcBool remove = FcFalse; - /* - * Check each family - */ - for (fa = 0; !remove && - FcPatternGetString (pat, FC_FAMILY, - fa, &fam) == FcResultMatch; - fa++) - { - /* - * for exact match - */ - if (!FcStrCmpIgnoreBlanksAndCase (full, fam)) - { - remove = FcTrue; - break; - } - /* - * If the family is in the full name, check the - * combination of this family with every style - */ - if (!FcStrContainsIgnoreBlanksAndCase (full, fam)) - continue; - for (st = 0; !remove && - FcPatternGetString (pat, FC_STYLE, - st, &style) == FcResultMatch; - st++) - { - FcChar8 *both = FcStrPlus (fam, style); - - if (both) - { - if (FcStrCmpIgnoreBlanksAndCase (full, both) == 0) - remove = FcTrue; - free (both); - } - } - } - if (remove) - { - FcPatternRemove (pat, FC_FULLNAME, fn); - FcPatternRemove (pat, FC_FULLNAMELANG, fn); - fn--; - nfullname--; - nfullname_lang--; - } - } - if (FcDebug () & FC_DBG_SCANV) - for (fn = 0; FcPatternGetString (pat, FC_FULLNAME, fn, &full) == FcResultMatch; fn++) - printf ("Saving unique fullname %s\n", full); - } - if (!FcPatternAddString (pat, FC_FILE, file)) goto bail1; @@ -1365,8 +1467,13 @@ FcFreeTypeQuery (const FcChar8 *file, weight = FC_WEIGHT_BOLD; else if (os2->usWeightClass < 850) weight = FC_WEIGHT_EXTRABOLD; - else if (os2->usWeightClass < 950) + else if (os2->usWeightClass < 925) weight = FC_WEIGHT_BLACK; + else if (os2->usWeightClass < 1000) + weight = FC_WEIGHT_EXTRABLACK; + if ((FcDebug() & FC_DBG_SCANV) && weight != -1) + printf ("\tos2 weight class %d maps to weight %d\n", + os2->usWeightClass, weight); switch (os2->usWidthClass) { case 1: width = FC_WIDTH_ULTRACONDENSED; break; @@ -1379,15 +1486,18 @@ FcFreeTypeQuery (const FcChar8 *file, case 8: width = FC_WIDTH_EXTRAEXPANDED; break; case 9: width = FC_WIDTH_ULTRAEXPANDED; break; } + if ((FcDebug() & FC_DBG_SCANV) && width != -1) + printf ("\tos2 width class %d maps to width %d\n", + os2->usWidthClass, width); } - if (os2 && (complex = FcFontCapabilities(face))) + if (os2 && (complex_ = FcFontCapabilities(face))) { - if (!FcPatternAddString (pat, FC_CAPABILITY, complex)) + if (!FcPatternAddString (pat, FC_CAPABILITY, complex_)) { - free (complex); + free (complex_); goto bail1; } - free (complex); + free (complex_); } /* @@ -1400,7 +1510,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); @@ -1431,15 +1541,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)) { @@ -1462,10 +1571,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); } @@ -1495,6 +1604,12 @@ FcFreeTypeQuery (const FcChar8 *file, if (FcDebug() & FC_DBG_SCANV) printf ("\tStyle %s maps to slant %d\n", style, slant); } + if (decorative == FcFalse) + { + decorative = FcContainsDecorative (style) > 0; + if (FcDebug() & FC_DBG_SCANV) + printf ("\tStyle %s maps to decorative %d\n", style, decorative); + } } /* * Pull default values from the FreeType flags if more @@ -1518,7 +1633,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; @@ -1532,6 +1647,9 @@ FcFreeTypeQuery (const FcChar8 *file, if (!FcPatternAddString (pat, FC_FOUNDRY, foundry)) goto bail1; + if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative)) + goto bail1; + /* * Compute the unicode coverage for the font */ @@ -1542,7 +1660,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; @@ -1556,11 +1674,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 + * FT 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)) @@ -1587,39 +1710,9 @@ 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; -#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); - if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) - value = prop.u.integer; - else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL) - value = prop.u.cardinal; - else - goto nevermind; - if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0)) - goto nevermind; - - rc = MY_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) - value = prop.u.cardinal; - else - goto nevermind; - if(!FcPatternAddDouble(pat, FC_DPI, (double)value)) - goto nevermind; - - } - nevermind: - ; -#endif + goto bail2; } #if HAVE_FT_GET_X11_FONT_FORMAT /* @@ -1629,7 +1722,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 @@ -1638,12 +1731,6 @@ FcFreeTypeQuery (const FcChar8 *file, */ FcCharSetDestroy (cs); - /* - * Deallocate family/style values - */ - - FT_Done_Face (face); - FT_Done_FreeType (ftLibrary); return pat; bail2: @@ -1651,13 +1738,35 @@ bail2: bail1: FcPatternDestroy (pat); bail0: + return NULL; +} + +FcPattern * +FcFreeTypeQuery(const FcChar8 *file, + int id, + FcBlanks *blanks, + int *count) +{ + FT_Face face; + FT_Library ftLibrary; + FcPattern *pat = NULL; + + if (FT_Init_FreeType (&ftLibrary)) + return NULL; + + if (FT_New_Face (ftLibrary, (char *) file, id, &face)) + goto bail; + + *count = face->num_faces; + + pat = FcFreeTypeQueryFace (face, file, id, blanks); + FT_Done_Face (face); bail: FT_Done_FreeType (ftLibrary); - return 0; + return pat; } - /* * For our purposes, this approximation is sufficient */ @@ -2123,13 +2232,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 (sizeof (prefer_unicode) / sizeof (prefer_unicode[0])) +#define NUM_PREFER_UNICODE (int) (sizeof (prefer_unicode) / sizeof (prefer_unicode[0])) FcChar32 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map) @@ -2210,17 +2319,17 @@ 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; + FcGlyphId gn; - while ((gn = ucs_to_name[i])) + while ((gn = ucs_to_name[i]) != -1) { - if (gn->ucs == ucs4) - return gn->name; + if (glyphs[gn].ucs == ucs4) + return glyphs[gn].name; if (!r) { r = (int) (ucs4 % FC_GLYPHNAME_REHASH); @@ -2240,12 +2349,12 @@ FcGlyphNameToUcs4 (FcChar8 *name) FcChar32 h = FcHashGlyphName (name); int i = (int) (h % FC_GLYPHNAME_HASH); int r = 0; - FcGlyphName *gn; + FcGlyphId gn; - while ((gn = name_to_ucs[i])) + while ((gn = name_to_ucs[i]) != -1) { - if (!strcmp ((char *) name, (char *) gn->name)) - return gn->ucs; + if (!strcmp ((char *) name, (char *) glyphs[gn].name)) + return glyphs[gn].ucs; if (!r) { r = (int) (h % FC_GLYPHNAME_REHASH); @@ -2259,20 +2368,33 @@ FcGlyphNameToUcs4 (FcChar8 *name) return 0xffff; } +/* + * Work around a bug in some FreeType versions which fail + * to correctly bounds check glyph name buffers and overwrite + * the stack. As Postscript names have a limit of 127 characters, + * this should be sufficient. + */ + +#if FC_GLYPHNAME_MAXLEN < 127 +# define FC_GLYPHNAME_BUFLEN 127 +#else +# define FC_GLYPHNAME_BUFLEN FC_GLYPHNAME_MAXLEN +#endif + /* * Search through a font for a glyph by name. This is * currently a linear search as there doesn't appear to be * 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]; + FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 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 (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0) if (!strcmp ((char *) name, (char *) name_buf)) return gindex; } @@ -2295,6 +2417,10 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) int p; initial = 0; + + if (!face) + return 0; + /* * Find the current encoding */ @@ -2324,7 +2450,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 @@ -2339,7 +2465,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); @@ -2354,11 +2480,15 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) static FcBool FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, FT_UInt glyph, FcBlanks *blanks, - FT_Pos *advance) + FT_Pos *advance, + FcBool using_strike) { FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; FT_GlyphSlot slot; + if (using_strike) + load_flags &= ~FT_LOAD_NO_SCALE; + /* * When using scalable fonts, only report those glyphs * which can be scaled; otherwise those fonts will @@ -2407,15 +2537,12 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, return FcFalse; } -#define FC_MIN(a,b) ((a) < (b) ? (a) : (b)) -#define FC_MAX(a,b) ((a) > (b) ? (a) : (b)) -#define FC_ABS(a) ((a) < 0 ? -(a) : (a)) #define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33) -FcCharSet * -FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) +static FcCharSet * +FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing, FT_Int strike_index) { - FcChar32 page, off, max, ucs4; + FcChar32 page, off, ucs4; #ifdef CHECK FcChar32 font_max = 0; #endif @@ -2427,11 +2554,20 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) FT_UInt glyph; FT_Pos advance, advance_one = 0, advance_two = 0; FcBool has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse; + FcBool using_strike = FcFalse; fcs = FcCharSetCreate (); if (!fcs) goto bail0; +#if HAVE_FT_SELECT_SIZE + if (strike_index >= 0) { + if (FT_Select_Size (face, strike_index) != FT_Err_Ok) + goto bail1; + using_strike = FcTrue; + } +#endif + #ifdef CHECK printf ("Family %s style %s\n", face->family_name, face->style_name); #endif @@ -2451,24 +2587,35 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) ucs4 = map->ent[i].bmp; glyph = FT_Get_Char_Index (face, map->ent[i].encode); if (glyph && - FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) + FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike)) { - 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) @@ -2483,69 +2630,48 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) } else { - FT_UInt gindex; - - max = fcFontDecoders[o].max; - /* - * Find the first encoded character in the font - */ - if (FT_Get_Char_Index (face, 0)) - { - ucs4 = 0; - gindex = 1; - } - else + page = ~0; + leaf = NULL; + ucs4 = FT_Get_First_Char (face, &glyph); + while (glyph != 0) { - ucs4 = FT_Get_Next_Char (face, 0, &gindex); - if (!ucs4) - gindex = 0; - } - - while (gindex) - { - page = ucs4 >> 8; - leaf = 0; - while ((ucs4 >> 8) == page) + if (FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike)) { - glyph = FT_Get_Char_Index (face, ucs4); - if (glyph && FcFreeTypeCheckGlyph (face, ucs4, - glyph, blanks, &advance)) + if (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; - } - - if (!leaf) + else if (!APPROXIMATELY_EQUAL (advance, advance_one)) { - leaf = FcCharSetFindLeafCreate (fcs, ucs4); - if (!leaf) - goto bail1; + if (fixed_advance) + { + dual_advance = FcTrue; + fixed_advance = FcFalse; + advance_two = advance; + } + else if (!APPROXIMATELY_EQUAL (advance, advance_two)) + dual_advance = FcFalse; } - off = ucs4 & 0xff; - leaf->map[off >> 5] |= (1 << (off & 0x1f)); + } + + if ((ucs4 >> 8) != page) + { + page = (ucs4 >> 8); + leaf = FcCharSetFindLeafCreate (fcs, ucs4); + if (!leaf) + goto bail1; + } + off = ucs4 & 0xff; + leaf->map[off >> 5] |= (1 << (off & 0x1f)); #ifdef CHECK - if (ucs4 > font_max) - font_max = ucs4; + if (ucs4 > font_max) + font_max = ucs4; #endif - } - ucs4++; } - ucs4 = FT_Get_Next_Char (face, ucs4 - 1, &gindex); - if (!ucs4) - gindex = 0; + ucs4 = FT_Get_Next_Char (face, ucs4, &glyph); } #ifdef CHECK for (ucs4 = 0; ucs4 < 0x10000; ucs4++) @@ -2568,32 +2694,35 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) */ if (FcFreeTypeUseNames (face)) { - FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2]; + FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 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) + if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0) { ucs4 = FcGlyphNameToUcs4 (name_buf); if (ucs4 != 0xffff && - FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) + FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike)) { - 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; @@ -2616,7 +2745,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) if (has_char && !has_bit) { - if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) + if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike)) printf ("Bitmap missing broken char 0x%x\n", ucs4); else printf ("Bitmap missing char 0x%x\n", ucs4); @@ -2638,6 +2767,39 @@ bail0: return 0; } +FcCharSet * +FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) +{ + FcCharSet *cs; + + cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, -1); + /* + * Check for bitmap-only ttf fonts that are missing the glyf table. + * In that case, pick a size and look for glyphs in that size instead + */ + if (FcCharSetCount (cs) == 0) + { + /* Check for non-scalable TT fonts */ + if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) && + face->num_fixed_sizes > 0 && + FT_Get_Sfnt_Table (face, ft_sfnt_head)) + { + FT_Int strike_index = 0; + int i; + + /* Select the face closest to 16 pixels tall */ + for (i = 1; i < face->num_fixed_sizes; i++) { + if (abs (face->available_sizes[i].height - 16) < + abs (face->available_sizes[strike_index].height - 16)) + strike_index = i; + } + FcCharSetDestroy (cs); + cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, strike_index); + } + } + return cs; +} + FcCharSet * FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks) { @@ -2650,10 +2812,6 @@ FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks) #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' ) #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) #define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f') -#define TT_Err_Ok FT_Err_Ok -#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle -#define TTO_Err_Empty_Script 0x1005 -#define TTO_Err_Invalid_SubTable 0x1001 #define OTLAYOUT_HEAD "otlayout:" #define OTLAYOUT_HEAD_LEN 9 @@ -2669,7 +2827,7 @@ FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks) #define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x)) static void -addtag(FcChar8 *complex, FT_ULong tag) +addtag(FcChar8 *complex_, FT_ULong tag) { FcChar8 tagstring[OTLAYOUT_ID_LEN + 1]; @@ -2688,10 +2846,10 @@ addtag(FcChar8 *complex, FT_ULong tag) !FcIsValidScript(tagstring[3])) return; - if (*complex != '\0') - strcat (complex, " "); - strcat (complex, "otlayout:"); - strcat (complex, tagstring); + if (*complex_ != '\0') + strcat ((char *) complex_, " "); + strcat ((char *) complex_, "otlayout:"); + strcat ((char *) complex_, (char *) tagstring); } static int @@ -2703,89 +2861,86 @@ compareulong (const void *a, const void *b) } -static FT_Error -GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags, FT_UShort *script_count) +static int +GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags) { - FT_ULong cur_offset, new_offset, base_offset; - TT_Face tt_face = (TT_Face)face; + FT_ULong cur_offset, new_offset, base_offset; FT_Stream stream = face->stream; FT_Error error; - FT_UShort n, p; - FT_Memory memory = stream->memory; + FT_UShort n, p; + FT_Memory memory; + int script_count; - if ( !stream ) - return TT_Err_Invalid_Face_Handle; + if (!stream) + return 0; - if (( error = tt_face->goto_table( tt_face, tabletag, stream, 0 ) )) - return error; + memory = stream->memory; - base_offset = FT_STREAM_POS(); + if (( error = ftglue_face_goto_table( face, tabletag, stream ) )) + return 0; + + base_offset = ftglue_stream_pos ( stream ); /* skip version */ - if ( FT_STREAM_SEEK( base_offset + 4L ) || FT_FRAME_ENTER( 2L ) ) - return error; + if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) ) + return 0; - 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 ) - return error; + if ( ftglue_stream_seek( stream, new_offset ) != FT_Err_Ok ) + return 0; - base_offset = FT_STREAM_POS(); + base_offset = ftglue_stream_pos( stream ); - if ( FT_FRAME_ENTER( 2L ) ) - return error; + if ( ftglue_stream_frame_enter( stream, 2L ) ) + return 0; - *script_count = FT_GET_USHORT(); + script_count = GET_UShort (); - FT_FRAME_EXIT(); + ftglue_stream_frame_exit( stream ); - if ( FT_SET_ERROR (FT_MEM_ALLOC_ARRAY( *stags, *script_count, FT_ULong )) ) - return error; + *stags = malloc(script_count * sizeof (FT_ULong)); + if (!stags) + return 0; p = 0; - for ( n = 0; n < *script_count; n++ ) + 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 ) + if ( error == FT_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) - { - error = TTO_Err_Invalid_SubTable; goto Fail; - } - // sort the tag list before returning it - qsort(*stags, *script_count, sizeof(FT_ULong), compareulong); + /* sort the tag list before returning it */ + qsort(*stags, script_count, sizeof(FT_ULong), compareulong); - return TT_Err_Ok; + return script_count; Fail: - *script_count = 0; - FT_FREE( *stags ); - return error; + free(*stags); + *stags = NULL; + return 0; } static FcChar8 * @@ -2798,50 +2953,53 @@ FcFontCapabilities(FT_Face face) FT_UShort gsub_count=0, gpos_count=0; FT_ULong maxsize; FT_Memory memory = face->stream->memory; - FcChar8 *complex = NULL; + FcChar8 *complex_ = NULL; int indx1 = 0, indx2 = 0; err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len); issilgraphitefont = ( err == FT_Err_Ok); - 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; - + gpos_count = GetScriptTags(face, TTAG_GPOS, &gpostags); + gsub_count = GetScriptTags(face, TTAG_GSUB, &gsubtags); + if (!issilgraphitefont && !gsub_count && !gpos_count) goto bail; maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN + (issilgraphitefont ? 13 : 0)); - complex = malloc (sizeof (FcChar8) * maxsize); - if (!complex) + complex_ = malloc (sizeof (FcChar8) * maxsize); + if (!complex_) goto bail; - complex[0] = '\0'; + complex_[0] = '\0'; if (issilgraphitefont) - strcpy(complex, "ttable:Silf "); + strcpy((char *) complex_, "ttable:Silf "); while ((indx1 < gsub_count) || (indx2 < gpos_count)) { if (indx1 == gsub_count) { - addtag(complex, gpostags[indx2]); + addtag(complex_, gpostags[indx2]); indx2++; } else if ((indx2 == gpos_count) || (gsubtags[indx1] < gpostags[indx2])) { - addtag(complex, gsubtags[indx1]); + addtag(complex_, gsubtags[indx1]); indx1++; } else if (gsubtags[indx1] == gpostags[indx2]) { - addtag(complex, gsubtags[indx1]); + addtag(complex_, gsubtags[indx1]); indx1++; indx2++; } else { - addtag(complex, gpostags[indx2]); + addtag(complex_, gpostags[indx2]); indx2++; } } if (FcDebug () & FC_DBG_SCANV) - printf("complex features in this font: %s\n", complex); + printf("complex_ features in this font: %s\n", complex_); bail: - FT_FREE(gsubtags); - FT_FREE(gpostags); - return complex; + free(gsubtags); + free(gpostags); + return complex_; } + +#define __fcfreetype__ +#include "fcaliastail.h" +#include "fcftaliastail.h" +#undef __fcfreetype__