diff options
Diffstat (limited to 'chromium/third_party/fontconfig/src/src/fcfreetype.c')
-rw-r--r-- | chromium/third_party/fontconfig/src/src/fcfreetype.c | 877 |
1 files changed, 369 insertions, 508 deletions
diff --git a/chromium/third_party/fontconfig/src/src/fcfreetype.c b/chromium/third_party/fontconfig/src/src/fcfreetype.c index e39430762c7..b4d926d4667 100644 --- a/chromium/third_party/fontconfig/src/src/fcfreetype.c +++ b/chromium/third_party/fontconfig/src/src/fcfreetype.c @@ -62,6 +62,7 @@ #include FT_BDF_H #include FT_MODULE_H #endif +#include FT_MULTIPLE_MASTERS_H #include "ftglue.h" @@ -558,6 +559,139 @@ FcFontCapabilities(FT_Face face); #define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0])) + +/* From http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT */ +static const FcChar16 fcMacRomanNonASCIIToUnicode[128] = { + /*0x80*/ 0x00C4, /* LATIN CAPITAL LETTER A WITH DIAERESIS */ + /*0x81*/ 0x00C5, /* LATIN CAPITAL LETTER A WITH RING ABOVE */ + /*0x82*/ 0x00C7, /* LATIN CAPITAL LETTER C WITH CEDILLA */ + /*0x83*/ 0x00C9, /* LATIN CAPITAL LETTER E WITH ACUTE */ + /*0x84*/ 0x00D1, /* LATIN CAPITAL LETTER N WITH TILDE */ + /*0x85*/ 0x00D6, /* LATIN CAPITAL LETTER O WITH DIAERESIS */ + /*0x86*/ 0x00DC, /* LATIN CAPITAL LETTER U WITH DIAERESIS */ + /*0x87*/ 0x00E1, /* LATIN SMALL LETTER A WITH ACUTE */ + /*0x88*/ 0x00E0, /* LATIN SMALL LETTER A WITH GRAVE */ + /*0x89*/ 0x00E2, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */ + /*0x8A*/ 0x00E4, /* LATIN SMALL LETTER A WITH DIAERESIS */ + /*0x8B*/ 0x00E3, /* LATIN SMALL LETTER A WITH TILDE */ + /*0x8C*/ 0x00E5, /* LATIN SMALL LETTER A WITH RING ABOVE */ + /*0x8D*/ 0x00E7, /* LATIN SMALL LETTER C WITH CEDILLA */ + /*0x8E*/ 0x00E9, /* LATIN SMALL LETTER E WITH ACUTE */ + /*0x8F*/ 0x00E8, /* LATIN SMALL LETTER E WITH GRAVE */ + /*0x90*/ 0x00EA, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */ + /*0x91*/ 0x00EB, /* LATIN SMALL LETTER E WITH DIAERESIS */ + /*0x92*/ 0x00ED, /* LATIN SMALL LETTER I WITH ACUTE */ + /*0x93*/ 0x00EC, /* LATIN SMALL LETTER I WITH GRAVE */ + /*0x94*/ 0x00EE, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */ + /*0x95*/ 0x00EF, /* LATIN SMALL LETTER I WITH DIAERESIS */ + /*0x96*/ 0x00F1, /* LATIN SMALL LETTER N WITH TILDE */ + /*0x97*/ 0x00F3, /* LATIN SMALL LETTER O WITH ACUTE */ + /*0x98*/ 0x00F2, /* LATIN SMALL LETTER O WITH GRAVE */ + /*0x99*/ 0x00F4, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */ + /*0x9A*/ 0x00F6, /* LATIN SMALL LETTER O WITH DIAERESIS */ + /*0x9B*/ 0x00F5, /* LATIN SMALL LETTER O WITH TILDE */ + /*0x9C*/ 0x00FA, /* LATIN SMALL LETTER U WITH ACUTE */ + /*0x9D*/ 0x00F9, /* LATIN SMALL LETTER U WITH GRAVE */ + /*0x9E*/ 0x00FB, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */ + /*0x9F*/ 0x00FC, /* LATIN SMALL LETTER U WITH DIAERESIS */ + /*0xA0*/ 0x2020, /* DAGGER */ + /*0xA1*/ 0x00B0, /* DEGREE SIGN */ + /*0xA2*/ 0x00A2, /* CENT SIGN */ + /*0xA3*/ 0x00A3, /* POUND SIGN */ + /*0xA4*/ 0x00A7, /* SECTION SIGN */ + /*0xA5*/ 0x2022, /* BULLET */ + /*0xA6*/ 0x00B6, /* PILCROW SIGN */ + /*0xA7*/ 0x00DF, /* LATIN SMALL LETTER SHARP S */ + /*0xA8*/ 0x00AE, /* REGISTERED SIGN */ + /*0xA9*/ 0x00A9, /* COPYRIGHT SIGN */ + /*0xAA*/ 0x2122, /* TRADE MARK SIGN */ + /*0xAB*/ 0x00B4, /* ACUTE ACCENT */ + /*0xAC*/ 0x00A8, /* DIAERESIS */ + /*0xAD*/ 0x2260, /* NOT EQUAL TO */ + /*0xAE*/ 0x00C6, /* LATIN CAPITAL LETTER AE */ + /*0xAF*/ 0x00D8, /* LATIN CAPITAL LETTER O WITH STROKE */ + /*0xB0*/ 0x221E, /* INFINITY */ + /*0xB1*/ 0x00B1, /* PLUS-MINUS SIGN */ + /*0xB2*/ 0x2264, /* LESS-THAN OR EQUAL TO */ + /*0xB3*/ 0x2265, /* GREATER-THAN OR EQUAL TO */ + /*0xB4*/ 0x00A5, /* YEN SIGN */ + /*0xB5*/ 0x00B5, /* MICRO SIGN */ + /*0xB6*/ 0x2202, /* PARTIAL DIFFERENTIAL */ + /*0xB7*/ 0x2211, /* N-ARY SUMMATION */ + /*0xB8*/ 0x220F, /* N-ARY PRODUCT */ + /*0xB9*/ 0x03C0, /* GREEK SMALL LETTER PI */ + /*0xBA*/ 0x222B, /* INTEGRAL */ + /*0xBB*/ 0x00AA, /* FEMININE ORDINAL INDICATOR */ + /*0xBC*/ 0x00BA, /* MASCULINE ORDINAL INDICATOR */ + /*0xBD*/ 0x03A9, /* GREEK CAPITAL LETTER OMEGA */ + /*0xBE*/ 0x00E6, /* LATIN SMALL LETTER AE */ + /*0xBF*/ 0x00F8, /* LATIN SMALL LETTER O WITH STROKE */ + /*0xC0*/ 0x00BF, /* INVERTED QUESTION MARK */ + /*0xC1*/ 0x00A1, /* INVERTED EXCLAMATION MARK */ + /*0xC2*/ 0x00AC, /* NOT SIGN */ + /*0xC3*/ 0x221A, /* SQUARE ROOT */ + /*0xC4*/ 0x0192, /* LATIN SMALL LETTER F WITH HOOK */ + /*0xC5*/ 0x2248, /* ALMOST EQUAL TO */ + /*0xC6*/ 0x2206, /* INCREMENT */ + /*0xC7*/ 0x00AB, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ + /*0xC8*/ 0x00BB, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ + /*0xC9*/ 0x2026, /* HORIZONTAL ELLIPSIS */ + /*0xCA*/ 0x00A0, /* NO-BREAK SPACE */ + /*0xCB*/ 0x00C0, /* LATIN CAPITAL LETTER A WITH GRAVE */ + /*0xCC*/ 0x00C3, /* LATIN CAPITAL LETTER A WITH TILDE */ + /*0xCD*/ 0x00D5, /* LATIN CAPITAL LETTER O WITH TILDE */ + /*0xCE*/ 0x0152, /* LATIN CAPITAL LIGATURE OE */ + /*0xCF*/ 0x0153, /* LATIN SMALL LIGATURE OE */ + /*0xD0*/ 0x2013, /* EN DASH */ + /*0xD1*/ 0x2014, /* EM DASH */ + /*0xD2*/ 0x201C, /* LEFT DOUBLE QUOTATION MARK */ + /*0xD3*/ 0x201D, /* RIGHT DOUBLE QUOTATION MARK */ + /*0xD4*/ 0x2018, /* LEFT SINGLE QUOTATION MARK */ + /*0xD5*/ 0x2019, /* RIGHT SINGLE QUOTATION MARK */ + /*0xD6*/ 0x00F7, /* DIVISION SIGN */ + /*0xD7*/ 0x25CA, /* LOZENGE */ + /*0xD8*/ 0x00FF, /* LATIN SMALL LETTER Y WITH DIAERESIS */ + /*0xD9*/ 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ + /*0xDA*/ 0x2044, /* FRACTION SLASH */ + /*0xDB*/ 0x20AC, /* EURO SIGN */ + /*0xDC*/ 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */ + /*0xDD*/ 0x203A, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */ + /*0xDE*/ 0xFB01, /* LATIN SMALL LIGATURE FI */ + /*0xDF*/ 0xFB02, /* LATIN SMALL LIGATURE FL */ + /*0xE0*/ 0x2021, /* DOUBLE DAGGER */ + /*0xE1*/ 0x00B7, /* MIDDLE DOT */ + /*0xE2*/ 0x201A, /* SINGLE LOW-9 QUOTATION MARK */ + /*0xE3*/ 0x201E, /* DOUBLE LOW-9 QUOTATION MARK */ + /*0xE4*/ 0x2030, /* PER MILLE SIGN */ + /*0xE5*/ 0x00C2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + /*0xE6*/ 0x00CA, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + /*0xE7*/ 0x00C1, /* LATIN CAPITAL LETTER A WITH ACUTE */ + /*0xE8*/ 0x00CB, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ + /*0xE9*/ 0x00C8, /* LATIN CAPITAL LETTER E WITH GRAVE */ + /*0xEA*/ 0x00CD, /* LATIN CAPITAL LETTER I WITH ACUTE */ + /*0xEB*/ 0x00CE, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + /*0xEC*/ 0x00CF, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ + /*0xED*/ 0x00CC, /* LATIN CAPITAL LETTER I WITH GRAVE */ + /*0xEE*/ 0x00D3, /* LATIN CAPITAL LETTER O WITH ACUTE */ + /*0xEF*/ 0x00D4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + /*0xF0*/ 0xF8FF, /* Apple logo */ + /*0xF1*/ 0x00D2, /* LATIN CAPITAL LETTER O WITH GRAVE */ + /*0xF2*/ 0x00DA, /* LATIN CAPITAL LETTER U WITH ACUTE */ + /*0xF3*/ 0x00DB, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + /*0xF4*/ 0x00D9, /* LATIN CAPITAL LETTER U WITH GRAVE */ + /*0xF5*/ 0x0131, /* LATIN SMALL LETTER DOTLESS I */ + /*0xF6*/ 0x02C6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ + /*0xF7*/ 0x02DC, /* SMALL TILDE */ + /*0xF8*/ 0x00AF, /* MACRON */ + /*0xF9*/ 0x02D8, /* BREVE */ + /*0xFA*/ 0x02D9, /* DOT ABOVE */ + /*0xFB*/ 0x02DA, /* RING ABOVE */ + /*0xFC*/ 0x00B8, /* CEDILLA */ + /*0xFD*/ 0x02DD, /* DOUBLE ACUTE ACCENT */ + /*0xFE*/ 0x02DB, /* OGONEK */ + /*0xFF*/ 0x02C7, /* CARON */ +}; + #if USE_ICONV #include <iconv.h> #endif @@ -696,6 +830,35 @@ FcSfntNameTranscode (FT_SfntName *sname) *u8 = '\0'; goto done; } + if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN)) + { + FcChar8 *src = sname->string; + int src_len = sname->string_len; + int olen; + FcChar8 *u8; + FcChar32 ucs4; + + /* + * Convert Latin1 to Utf8. Freed below + */ + utf8 = malloc (src_len * 3 + 1); + if (!utf8) + return 0; + + u8 = utf8; + while (src_len > 0) + { + ucs4 = *src++; + if (ucs4 >= 128) + ucs4 = fcMacRomanNonASCIIToUnicode[ucs4 - 128]; + src_len--; + olen = FcUcs4ToUtf8 (ucs4, u8); + u8 += olen; + } + *u8 = '\0'; + goto done; + } + #if USE_ICONV cd = iconv_open ("UTF-8", fromcode); if (cd && cd != (iconv_t) (-1)) @@ -816,76 +979,6 @@ FcNoticeFoundry(const FT_String *notice) return 0; } -static FcBool -FcVendorMatch(const FT_Char vendor[4], const FT_Char *vendor_string) -{ - /* vendor is not necessarily NUL-terminated. */ - int i, len; - - len = strlen((char *) vendor_string); - if (memcmp(vendor, vendor_string, len) != 0) - return FcFalse; - for (i = len; i < 4; i++) - if (vendor[i] != ' ' && vendor[i] != '\0') - return FcFalse; - return FcTrue; -} - -/* This table is partly taken from ttmkfdir by Joerg Pommnitz. */ - -/* It should not contain useless entries (such as UNKN) nor duplicate - entries for padding both with spaces and NULs. */ - -static const struct { - const FT_Char vendor[5]; - const FcChar8 foundry[13]; -} FcVendorFoundries[] = { - { "ADBE", "adobe"}, - { "AGFA", "agfa"}, - { "ALTS", "altsys"}, - { "APPL", "apple"}, - { "ARPH", "arphic"}, - { "ATEC", "alltype"}, - { "B&H", "b&h"}, - { "BITS", "bitstream"}, - { "CANO", "cannon"}, - { "CLM", "culmus"}, - { "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 (int) (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0])) - -static const FcChar8 * -FcVendorFoundry(const FT_Char vendor[4]) -{ - int i; - - if (vendor) - for(i = 0; i < NUM_VENDOR_FOUNDRIES; i++) - if (FcVendorMatch (vendor, FcVendorFoundries[i].vendor)) - return FcVendorFoundries[i].foundry; - return 0; -} - typedef struct _FcStringConst { const FcChar8 *name; int value; @@ -933,6 +1026,8 @@ static const FcStringConst weightConsts[] = { { (FC8) "thin", FC_WEIGHT_THIN }, { (FC8) "extralight", FC_WEIGHT_EXTRALIGHT }, { (FC8) "ultralight", FC_WEIGHT_ULTRALIGHT }, + { (FC8) "demilight", FC_WEIGHT_DEMILIGHT }, + { (FC8) "semilight", FC_WEIGHT_SEMILIGHT }, { (FC8) "light", FC_WEIGHT_LIGHT }, { (FC8) "book", FC_WEIGHT_BOOK }, { (FC8) "regular", FC_WEIGHT_REGULAR }, @@ -1075,9 +1170,16 @@ FcFreeTypeQueryFace (const FT_Face face, #if 0 FcChar8 *family = 0; #endif - FcChar8 *complex_; + FcChar8 *complex_, *foundry_ = NULL; const FcChar8 *foundry = 0; int spacing; + + /* Support for glyph-variation named-instances. */ + FT_MM_Var *master = NULL; + FT_Var_Named_Style *instance = NULL; + double weight_mult = 1.0; + double width_mult = 1.0; + TT_OS2 *os2; #if HAVE_FT_GET_PS_FONT_INFO PS_FontInfoRec psfontinfo; @@ -1104,22 +1206,70 @@ FcFreeTypeQueryFace (const FT_Face face, char psname[256]; const char *tmp; - FcChar8 *hashstr = NULL; - FT_Error err; - FT_ULong len = 0, alen; + FcRange *r = NULL; + + FcBool symbol = FcFalse; + + FcInitDebug (); /* We might be called with no initizalization whatsoever. */ pat = FcPatternCreate (); if (!pat) goto bail0; - if (!FcPatternAddBool (pat, FC_OUTLINE, - (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0)) - goto bail1; + { + int has_outline = !!(face->face_flags & FT_FACE_FLAG_SCALABLE); + int has_color = 0; - if (!FcPatternAddBool (pat, FC_SCALABLE, - (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0)) - goto bail1; +#ifdef FT_FACE_FLAG_COLOR + has_color = !!(face->face_flags & FT_FACE_FLAG_COLOR); +#endif + + if (!FcPatternAddBool (pat, FC_OUTLINE, has_outline)) + goto bail1; + +#ifdef FT_FACE_FLAG_COLOR + if (!FcPatternAddBool (pat, FC_COLOR, has_color)) + goto bail1; +#endif + + /* All color fonts are designed to be scaled, even if they only have + * bitmap strikes. Client is responsible to scale the bitmaps. This + * is in constrast to non-color strikes... */ + if (!FcPatternAddBool (pat, FC_SCALABLE, has_outline || has_color)) + goto bail1; + } + + if (id >> 16) + { + if (!FT_Get_MM_Var (face, &master)) + instance = &master->namedstyle[(id >> 16) - 1]; + + if (instance) + { + /* Pull out weight and width from named-instance. */ + unsigned int i; + + for (i = 0; i < master->num_axis; i++) + { + double value = instance->coords[i] / (double) (1 << 16); + double default_value = master->axis[i].def / (double) (1 << 16); + double mult = value / default_value; + //printf ("named-instance, axis %d tag %lx value %g\n", i, master->axis[i].tag, value); + switch (master->axis[i].tag) + { + case FT_MAKE_TAG ('w','g','h','t'): + weight_mult = mult; + break; + + case FT_MAKE_TAG ('w','d','t','h'): + width_mult = mult; + break; + /* TODO optical size! */ + } + } + } + } /* * Get the OS/2 table @@ -1135,7 +1285,15 @@ FcFreeTypeQueryFace (const FT_Face face, */ if (os2 && os2->version >= 0x0001 && os2->version != 0xffff) - foundry = FcVendorFoundry(os2->achVendID); + { + if (os2->achVendID && os2->achVendID[0] != 0) + { + foundry_ = (FcChar8 *) malloc (sizeof (os2->achVendID) + 1); + memcpy ((void *)foundry_, os2->achVendID, sizeof (os2->achVendID)); + foundry_[sizeof (os2->achVendID)] = 0; + foundry = foundry_; + } + } if (FcDebug () & FC_DBG_SCANV) printf ("\n"); @@ -1170,6 +1328,19 @@ FcFreeTypeQueryFace (const FT_Face face, if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0) continue; + + if (instance) + { + /* For named-instances, we regular style nameIDs, + * and map the instance's strid to FONT_SUBFAMILY. */ + if (sname.name_id == TT_NAME_ID_WWS_SUBFAMILY || + sname.name_id == TT_NAME_ID_PREFERRED_SUBFAMILY || + sname.name_id == TT_NAME_ID_FONT_SUBFAMILY) + continue; + if (sname.name_id == instance->strid) + sname.name_id = TT_NAME_ID_FONT_SUBFAMILY; + } + if (sname.name_id != nameid) continue; @@ -1283,10 +1454,10 @@ FcFreeTypeQueryFace (const FT_Face face, free (utf8); if (lang) { - /* pad lang list with 'xx' to line up with elt */ + /* pad lang list with 'und' to line up with elt */ while (*nlangp < *np) { - if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "xx")) + if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und")) goto bail1; ++*nlangp; } @@ -1309,6 +1480,8 @@ FcFreeTypeQueryFace (const FT_Face face, printf ("using FreeType family \"%s\"\n", face->family_name); if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name)) goto bail1; + if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en")) + goto bail1; ++nfamily; } @@ -1319,10 +1492,12 @@ FcFreeTypeQueryFace (const FT_Face face, printf ("using FreeType style \"%s\"\n", face->style_name); if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name)) goto bail1; + if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en")) + goto bail1; ++nstyle; } - if (!nfamily) + if (!nfamily && file && *file) { FcChar8 *start, *end; FcChar8 *family; @@ -1391,12 +1566,13 @@ FcFreeTypeQueryFace (const FT_Face face, } else { - strcpy (psname, tmp); + strncpy (psname, tmp, 255); + psname[255] = 0; } if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname)) goto bail1; - if (!FcPatternAddString (pat, FC_FILE, file)) + if (file && *file && !FcPatternAddString (pat, FC_FILE, file)) goto bail1; if (!FcPatternAddInteger (pat, FC_INDEX, id)) @@ -1463,33 +1639,22 @@ FcFreeTypeQueryFace (const FT_Face face, if (os2 && os2->version != 0xffff) { - if (os2->usWeightClass == 0) - ; - else if (os2->usWeightClass < 150) - weight = FC_WEIGHT_THIN; - else if (os2->usWeightClass < 250) - weight = FC_WEIGHT_EXTRALIGHT; - else if (os2->usWeightClass < 350) - weight = FC_WEIGHT_LIGHT; - else if (os2->usWeightClass < 450) - weight = FC_WEIGHT_REGULAR; - else if (os2->usWeightClass < 550) - weight = FC_WEIGHT_MEDIUM; - else if (os2->usWeightClass < 650) - weight = FC_WEIGHT_SEMIBOLD; - else if (os2->usWeightClass < 750) - weight = FC_WEIGHT_BOLD; - else if (os2->usWeightClass < 850) - weight = FC_WEIGHT_EXTRABOLD; - else if (os2->usWeightClass < 925) - weight = FC_WEIGHT_BLACK; - else if (os2->usWeightClass < 1000) - weight = FC_WEIGHT_EXTRABLACK; + weight = os2->usWeightClass; + if (weight < 10 && weight_mult != 1.0) + { + /* Work around bad values by cleaning them up before + * multiplying by weight_mult. */ + weight = FcWeightToOpenType (FcWeightFromOpenType (weight)); + } + weight = FcWeightFromOpenType ((int) (weight * weight_mult + .5)); if ((FcDebug() & FC_DBG_SCANV) && weight != -1) - printf ("\tos2 weight class %d maps to weight %d\n", - os2->usWeightClass, weight); + printf ("\tos2 weight class %d multiplier %g maps to weight %d\n", + os2->usWeightClass, weight_mult, weight); - switch (os2->usWidthClass) { + /* TODO: + * Add FcWidthFromOpenType and FcWidthToOpenType, + * and apply width_mult post-conversion? */ + switch ((int) (os2->usWidthClass * width_mult + .5)) { case 1: width = FC_WIDTH_ULTRACONDENSED; break; case 2: width = FC_WIDTH_EXTRACONDENSED; break; case 3: width = FC_WIDTH_CONDENSED; break; @@ -1501,8 +1666,8 @@ FcFreeTypeQueryFace (const FT_Face face, 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); + printf ("\tos2 width class %d multiplier %g maps to width %d\n", + os2->usWidthClass, width_mult, width); } if (os2 && (complex_ = FcFontCapabilities(face))) { @@ -1514,6 +1679,25 @@ FcFreeTypeQueryFace (const FT_Face face, free (complex_); } +#if defined (HAVE_TT_OS2_USUPPEROPTICALPOINTSIZE) && defined (HAVE_TT_OS2_USLOWEROPTICALPOINTSIZE) + if (os2 && os2->version >= 0x0005 && os2->version != 0xffff) + { + double lower_size, upper_size; + + /* usLowerPointSize and usUpperPointSize is actually twips */ + lower_size = os2->usLowerOpticalPointSize / 20.0L; + upper_size = os2->usUpperOpticalPointSize / 20.0L; + + r = FcRangeCreateDouble (lower_size, upper_size); + if (!FcPatternAddRange (pat, FC_SIZE, r)) + { + FcRangeDestroy (r); + goto bail1; + } + FcRangeDestroy (r); + } +#endif + /* * Type 1: Check for FontInfo dictionary information * Code from g2@magestudios.net (Gerard Escalante) @@ -1586,7 +1770,7 @@ FcFreeTypeQueryFace (const FT_Face face, } if (width == -1 && FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 && - prop.type == BDF_PROPERTY_TYPE_ATOM) + prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL) { width = FcIsWidth ((FcChar8 *) prop.u.atom); if (FcDebug () & FC_DBG_SCANV) @@ -1664,46 +1848,6 @@ FcFreeTypeQueryFace (const FT_Face face, if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative)) goto bail1; - err = FT_Load_Sfnt_Table (face, 0, 0, NULL, &len); - if (err == FT_Err_Ok) - { - char *fontdata; - - alen = (len + 63) & ~63; - fontdata = malloc (alen); - if (!fontdata) - goto bail3; - err = FT_Load_Sfnt_Table (face, 0, 0, (FT_Byte *)fontdata, &len); - if (err != FT_Err_Ok) - { - free (fontdata); - goto bail3; - } - memset (&fontdata[len], 0, alen - len); - hashstr = FcHashGetSHA256DigestFromMemory (fontdata, len); - free (fontdata); - } - else if (err == FT_Err_Invalid_Face_Handle) - { - /* font may not support SFNT. falling back to - * read the font data from file directly - */ - hashstr = FcHashGetSHA256DigestFromFile (file); - } - else - { - goto bail3; - } - if (hashstr) - { - if (!FcPatternAddString (pat, FC_HASH, hashstr)) - { - free (hashstr); - goto bail1; - } - free (hashstr); - } -bail3: /* * Compute the unicode coverage for the font @@ -1712,11 +1856,16 @@ bail3: if (!cs) goto bail1; + /* The FcFreeTypeCharSetAndSpacing() chose the encoding; test it for symbol. */ + symbol = face->charmap && face->charmap->encoding == FT_ENCODING_MS_SYMBOL; + if (!FcPatternAddBool (pat, FC_SYMBOL, symbol)) + goto bail1; + #if HAVE_FT_GET_BDF_PROPERTY /* For PCF fonts, override the computed spacing with the one from the property */ if(FT_Get_BDF_Property(face, "SPACING", &prop) == 0 && - prop.type == BDF_PROPERTY_TYPE_ATOM) { + prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL) { if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C")) spacing = FC_CHARCELL; else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M")) @@ -1744,9 +1893,18 @@ bail3: if (!FcPatternAddCharSet (pat, FC_CHARSET, cs)) goto bail2; - ls = FcFreeTypeLangSet (cs, exclusiveLang); - if (!ls) - goto bail2; + if (!symbol) + { + ls = FcFreeTypeLangSet (cs, exclusiveLang); + if (!ls) + goto bail2; + } + else + { + /* Symbol fonts don't cover any language, even though they + * claim to support Latin1 range. */ + ls = FcLangSetCreate (); + } if (!FcPatternAddLangSet (pat, FC_LANG, ls)) { @@ -1786,6 +1944,13 @@ bail3: * Drop our reference to the charset */ FcCharSetDestroy (cs); + if (foundry_) + free (foundry_); + + if (master) + { + /* TODO: How to free master?! */ + } return pat; @@ -1793,6 +1958,8 @@ bail2: FcCharSetDestroy (cs); bail1: FcPatternDestroy (pat); + if (foundry_) + free (foundry_); bail0: return NULL; } @@ -1833,282 +2000,12 @@ bail: #warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer" #endif -typedef struct _FcCharEnt { - FcChar16 bmp; - unsigned char encode; -} FcCharEnt; - -struct _FcCharMap { - const FcCharEnt *ent; - int nent; -}; - -typedef struct _FcFontDecode { - FT_Encoding encoding; - const FcCharMap *map; - FcChar32 max; -} FcFontDecode; - -static const FcCharEnt AdobeSymbolEnt[] = { - { 0x0020, 0x20 }, /* SPACE # space */ - { 0x0021, 0x21 }, /* EXCLAMATION MARK # exclam */ - { 0x0023, 0x23 }, /* NUMBER SIGN # numbersign */ - { 0x0025, 0x25 }, /* PERCENT SIGN # percent */ - { 0x0026, 0x26 }, /* AMPERSAND # ampersand */ - { 0x0028, 0x28 }, /* LEFT PARENTHESIS # parenleft */ - { 0x0029, 0x29 }, /* RIGHT PARENTHESIS # parenright */ - { 0x002B, 0x2B }, /* PLUS SIGN # plus */ - { 0x002C, 0x2C }, /* COMMA # comma */ - { 0x002E, 0x2E }, /* FULL STOP # period */ - { 0x002F, 0x2F }, /* SOLIDUS # slash */ - { 0x0030, 0x30 }, /* DIGIT ZERO # zero */ - { 0x0031, 0x31 }, /* DIGIT ONE # one */ - { 0x0032, 0x32 }, /* DIGIT TWO # two */ - { 0x0033, 0x33 }, /* DIGIT THREE # three */ - { 0x0034, 0x34 }, /* DIGIT FOUR # four */ - { 0x0035, 0x35 }, /* DIGIT FIVE # five */ - { 0x0036, 0x36 }, /* DIGIT SIX # six */ - { 0x0037, 0x37 }, /* DIGIT SEVEN # seven */ - { 0x0038, 0x38 }, /* DIGIT EIGHT # eight */ - { 0x0039, 0x39 }, /* DIGIT NINE # nine */ - { 0x003A, 0x3A }, /* COLON # colon */ - { 0x003B, 0x3B }, /* SEMICOLON # semicolon */ - { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */ - { 0x003D, 0x3D }, /* EQUALS SIGN # equal */ - { 0x003E, 0x3E }, /* GREATER-THAN SIGN # greater */ - { 0x003F, 0x3F }, /* QUESTION MARK # question */ - { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET # bracketleft */ - { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET # bracketright */ - { 0x005F, 0x5F }, /* LOW LINE # underscore */ - { 0x007B, 0x7B }, /* LEFT CURLY BRACKET # braceleft */ - { 0x007C, 0x7C }, /* VERTICAL LINE # bar */ - { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET # braceright */ - { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */ - { 0x00AC, 0xD8 }, /* NOT SIGN # logicalnot */ - { 0x00B0, 0xB0 }, /* DEGREE SIGN # degree */ - { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN # plusminus */ - { 0x00B5, 0x6D }, /* MICRO SIGN # mu */ - { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN # multiply */ - { 0x00F7, 0xB8 }, /* DIVISION SIGN # divide */ - { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */ - { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA # Alpha */ - { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA # Beta */ - { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA # Gamma */ - { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA # Delta */ - { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON # Epsilon */ - { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA # Zeta */ - { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA # Eta */ - { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA # Theta */ - { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA # Iota */ - { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA # Kappa */ - { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA # Lambda */ - { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU # Mu */ - { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU # Nu */ - { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI # Xi */ - { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON # Omicron */ - { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI # Pi */ - { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO # Rho */ - { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA # Sigma */ - { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU # Tau */ - { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON # Upsilon */ - { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI # Phi */ - { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI # Chi */ - { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI # Psi */ - { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA # Omega */ - { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA # alpha */ - { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA # beta */ - { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA # gamma */ - { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA # delta */ - { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON # epsilon */ - { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA # zeta */ - { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */ - { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA # theta */ - { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA # iota */ - { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA # kappa */ - { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA # lambda */ - { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU # mu */ - { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU # nu */ - { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI # xi */ - { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON # omicron */ - { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI # pi */ - { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */ - { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */ - { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA # sigma */ - { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */ - { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON # upsilon */ - { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */ - { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */ - { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */ - { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA # omega */ - { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL # theta1 */ - { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */ - { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL # phi1 */ - { 0x03D6, 0x76 }, /* GREEK PI SYMBOL # omega1 */ - { 0x2022, 0xB7 }, /* BULLET # bullet */ - { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS # ellipsis */ - { 0x2032, 0xA2 }, /* PRIME # minute */ - { 0x2033, 0xB2 }, /* DOUBLE PRIME # second */ - { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */ - { 0x20AC, 0xA0 }, /* EURO SIGN # Euro */ - { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */ - { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P # weierstrass */ - { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */ - { 0x2126, 0x57 }, /* OHM SIGN # Omega */ - { 0x2135, 0xC0 }, /* ALEF SYMBOL # aleph */ - { 0x2190, 0xAC }, /* LEFTWARDS ARROW # arrowleft */ - { 0x2191, 0xAD }, /* UPWARDS ARROW # arrowup */ - { 0x2192, 0xAE }, /* RIGHTWARDS ARROW # arrowright */ - { 0x2193, 0xAF }, /* DOWNWARDS ARROW # arrowdown */ - { 0x2194, 0xAB }, /* LEFT RIGHT ARROW # arrowboth */ - { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn */ - { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */ - { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW # arrowdblup */ - { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW # arrowdblright */ - { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */ - { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW # arrowdblboth */ - { 0x2200, 0x22 }, /* FOR ALL # universal */ - { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL # partialdiff */ - { 0x2203, 0x24 }, /* THERE EXISTS # existential */ - { 0x2205, 0xC6 }, /* EMPTY SET # emptyset */ - { 0x2206, 0x44 }, /* INCREMENT # Delta */ - { 0x2207, 0xD1 }, /* NABLA # gradient */ - { 0x2208, 0xCE }, /* ELEMENT OF # element */ - { 0x2209, 0xCF }, /* NOT AN ELEMENT OF # notelement */ - { 0x220B, 0x27 }, /* CONTAINS AS MEMBER # suchthat */ - { 0x220F, 0xD5 }, /* N-ARY PRODUCT # product */ - { 0x2211, 0xE5 }, /* N-ARY SUMMATION # summation */ - { 0x2212, 0x2D }, /* MINUS SIGN # minus */ - { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */ - { 0x2217, 0x2A }, /* ASTERISK OPERATOR # asteriskmath */ - { 0x221A, 0xD6 }, /* SQUARE ROOT # radical */ - { 0x221D, 0xB5 }, /* PROPORTIONAL TO # proportional */ - { 0x221E, 0xA5 }, /* INFINITY # infinity */ - { 0x2220, 0xD0 }, /* ANGLE # angle */ - { 0x2227, 0xD9 }, /* LOGICAL AND # logicaland */ - { 0x2228, 0xDA }, /* LOGICAL OR # logicalor */ - { 0x2229, 0xC7 }, /* INTERSECTION # intersection */ - { 0x222A, 0xC8 }, /* UNION # union */ - { 0x222B, 0xF2 }, /* INTEGRAL # integral */ - { 0x2234, 0x5C }, /* THEREFORE # therefore */ - { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */ - { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */ - { 0x2248, 0xBB }, /* ALMOST EQUAL TO # approxequal */ - { 0x2260, 0xB9 }, /* NOT EQUAL TO # notequal */ - { 0x2261, 0xBA }, /* IDENTICAL TO # equivalence */ - { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO # lessequal */ - { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO # greaterequal */ - { 0x2282, 0xCC }, /* SUBSET OF # propersubset */ - { 0x2283, 0xC9 }, /* SUPERSET OF # propersuperset */ - { 0x2284, 0xCB }, /* NOT A SUBSET OF # notsubset */ - { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO # reflexsubset */ - { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO # reflexsuperset */ - { 0x2295, 0xC5 }, /* CIRCLED PLUS # circleplus */ - { 0x2297, 0xC4 }, /* CIRCLED TIMES # circlemultiply */ - { 0x22A5, 0x5E }, /* UP TACK # perpendicular */ - { 0x22C5, 0xD7 }, /* DOT OPERATOR # dotmath */ - { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL # integraltp */ - { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL # integralbt */ - { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET # angleleft */ - { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET # angleright */ - { 0x25CA, 0xE0 }, /* LOZENGE # lozenge */ - { 0x2660, 0xAA }, /* BLACK SPADE SUIT # spade */ - { 0x2663, 0xA7 }, /* BLACK CLUB SUIT # club */ - { 0x2665, 0xA9 }, /* BLACK HEART SUIT # heart */ - { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT # diamond */ - { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF # copyrightserif (CUS) */ - { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF # registerserif (CUS) */ - { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF # trademarkserif (CUS) */ - { 0xF8E5, 0x60 }, /* RADICAL EXTENDER # radicalex (CUS) */ - { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER # arrowvertex (CUS) */ - { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) */ - { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF # registersans (CUS) */ - { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) */ - { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF # trademarksans (CUS) */ - { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */ - { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER # parenleftex (CUS) */ - { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM # parenleftbt (CUS) */ - { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) */ - { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) */ - { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) */ - { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */ - { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */ - { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) */ - { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */ - { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER # integralex (CUS) */ - { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP # parenrighttp (CUS) */ - { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER # parenrightex (CUS) */ - { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM # parenrightbt (CUS) */ - { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) */ - { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) */ - { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) */ - { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP # bracerighttp (CUS) */ - { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID # bracerightmid (CUS) */ - { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) */ +static const FT_Encoding fcFontEncodings[] = { + FT_ENCODING_UNICODE, + FT_ENCODING_MS_SYMBOL }; -static const FcCharMap AdobeSymbol = { - AdobeSymbolEnt, - sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]), -}; - -static const FcFontDecode fcFontDecoders[] = { - { ft_encoding_unicode, 0, (1 << 21) - 1 }, - { ft_encoding_symbol, &AdobeSymbol, (1 << 16) - 1 }, -}; - -#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) -{ - int low, high, mid; - FcChar16 bmp; - - low = 0; - high = map->nent - 1; - if (ucs4 < map->ent[low].bmp || map->ent[high].bmp < ucs4) - return ~0; - while (low <= high) - { - mid = (high + low) >> 1; - bmp = map->ent[mid].bmp; - if (ucs4 == bmp) - return (FT_ULong) map->ent[mid].encode; - if (ucs4 < bmp) - high = mid - 1; - else - low = mid + 1; - } - return ~0; -} - -FcChar32 -FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map) -{ - int i; - - for (i = 0; i < map->nent; i++) - if (map->ent[i].encode == private) - return (FcChar32) map->ent[i].bmp; - return ~0; -} - -const FcCharMap * -FcFreeTypeGetPrivateMap (FT_Encoding encoding) -{ - int i; - - for (i = 0; i < NUM_DECODE; i++) - if (fcFontDecoders[i].encoding == encoding) - return fcFontDecoders[i].map; - return 0; -} +#define NUM_DECODE (int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])) #include "../fc-glyphname/fcglyphname.h" @@ -2237,8 +2134,6 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) { int initial, offset, decode; FT_UInt glyphindex; - FcChar32 charcode; - int p; initial = 0; @@ -2251,37 +2146,39 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) if (face->charmap) { for (; initial < NUM_DECODE; initial++) - if (fcFontDecoders[initial].encoding == face->charmap->encoding) + if (fcFontEncodings[initial] == face->charmap->encoding) break; 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 */ for (offset = 0; offset < NUM_DECODE; offset++) { decode = (initial + offset) % NUM_DECODE; - if (!face->charmap || face->charmap->encoding != fcFontDecoders[decode].encoding) - if (FT_Select_Charmap (face, fcFontDecoders[decode].encoding) != 0) + if (!face->charmap || face->charmap->encoding != fcFontEncodings[decode]) + if (FT_Select_Charmap (face, fcFontEncodings[decode]) != 0) continue; - if (fcFontDecoders[decode].map) - { - charcode = FcFreeTypeUcs4ToPrivate (ucs4, fcFontDecoders[decode].map); - if (charcode == ~0U) - continue; - } - else - charcode = ucs4; - glyphindex = FT_Get_Char_Index (face, (FT_ULong) charcode); + glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4); if (glyphindex) return glyphindex; + if (ucs4 < 0x100 && face->charmap && + face->charmap->encoding == FT_ENCODING_MS_SYMBOL) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". + * + * See thread with subject "Webdings and other MS symbol + * fonts don't display" on mailing list from May 2015. + */ + glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4 + 0xF000); + if (glyphindex) + return glyphindex; + } } #if HAVE_FT_HAS_PS_GLYPH_NAMES /* @@ -2372,9 +2269,7 @@ FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing #endif FcCharSet *fcs; FcCharLeaf *leaf; - const FcCharMap *map; int o; - int i; FT_UInt glyph; FT_Pos advance, advance_one = 0, advance_two = 0; FcBool has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse; @@ -2397,62 +2292,9 @@ FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing #endif for (o = 0; o < NUM_DECODE; o++) { - if (FT_Select_Charmap (face, fcFontDecoders[o].encoding) != 0) + if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0) continue; - map = fcFontDecoders[o].map; - if (map) - { - /* - * Non-Unicode tables are easy; there's a list of all possible - * characters - */ - for (i = 0; i < map->nent; i++) - { - ucs4 = map->ent[i].bmp; - glyph = FT_Get_Char_Index (face, map->ent[i].encode); - if (glyph && - FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike)) - { - /* - * 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) - { - 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; - } - } - leaf = FcCharSetFindLeafCreate (fcs, ucs4); - if (!leaf) - goto bail1; - leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f)); -#ifdef CHECK - if (ucs4 > font_max) - font_max = ucs4; -#endif - } - } - } - else { page = ~0; leaf = NULL; @@ -2497,6 +2339,23 @@ FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing } ucs4 = FT_Get_Next_Char (face, ucs4, &glyph); } + if (fcFontEncodings[o] == FT_ENCODING_MS_SYMBOL) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". + * + * See thread with subject "Webdings and other MS symbol + * fonts don't display" on mailing list from May 2015. + */ + for (ucs4 = 0xF000; ucs4 < 0xF100; ucs4++) + { + if (FcCharSetHasChar (fcs, ucs4)) + FcCharSetAddChar (fcs, ucs4 - 0xF000); + } + } #ifdef CHECK for (ucs4 = 0; ucs4 < 0x10000; ucs4++) { @@ -2511,6 +2370,8 @@ FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing } #endif } + + break; } #if HAVE_FT_HAS_PS_GLYPH_NAMES /* |