static FcChar32 FcListValueHash (FcValue *value) { FcValue v = FcValueCanonicalize(value); switch (v.type) { case FcTypeVoid: return 0; case FcTypeInteger: return (FcChar32) v.u.i; case FcTypeDouble: return (FcChar32) (int) v.u.d; case FcTypeString: return FcStrHashIgnoreCase (v.u.s); case FcTypeBool: return (FcChar32) v.u.b; case FcTypeMatrix: return FcListMatrixHash (v.u.m); case FcTypeCharSet: return FcCharSetCount (v.u.c); case FcTypeFTFace: return (long) v.u.f; case FcTypeLangSet: return FcLangSetHash (v.u.l); } return 0; }
static FcBool empty_charset(FcPattern *pattern) { FcCharSet *charset; assert(FcPatternGetCharSet(pattern, FC_CHARSET, 0, &charset) == FcResultMatch); return FcCharSetCount(charset) == 0; }
int main (int argc, char **argv) { int index_set = 0; int set_index = 0; FcChar8 *lang = NULL; const FcCharSet *fcs_lang = NULL; int err = 0; int i; FT_Library ftlib; FcBool verbose = FcFalse; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; setlocale (LC_ALL, ""); #if HAVE_GETOPT_LONG while ((c = getopt_long (argc, argv, "i:l:mVhv", longopts, NULL)) != -1) #else while ((c = getopt (argc, argv, "i:l:mVhv")) != -1) #endif { switch (c) { case 'i': index_set = 1; set_index = atoi (optarg); break; case 'l': lang = (FcChar8 *) FcLangNormalize ((const FcChar8 *) optarg); break; case 'v': verbose = FcTrue; break; case 'V': fprintf (stderr, "fontconfig version %d.%d.%d\n", FC_MAJOR, FC_MINOR, FC_REVISION); exit (0); case 'h': usage (argv[0], 0); default: usage (argv[0], 1); } } i = optind; #else i = 1; verbose = FcTrue; #endif if (i == argc) usage (argv[0], 1); if (!lang) lang = FcLangNormalize ((const FcChar8 *) setlocale (LC_CTYPE, NULL)); if (lang) fcs_lang = FcLangGetCharSet (lang); if (FT_Init_FreeType (&ftlib)) { fprintf (stderr, _("Can't initalize FreeType library\n")); return 1; } for (; i < argc; i++) { int index; index = set_index; do { FT_Face face; FcCharSet *fcs, *fcs_sub; if (FT_New_Face (ftlib, argv[i], index, &face)) { if (!index_set && index > 0) break; fprintf (stderr, _("Unable to open %s\n"), argv[i]); err = 1; } else { FcChar32 count; fcs = FcFreeTypeCharSet (face, NULL); fcs_sub = FcCharSetSubtract (fcs_lang, fcs); count = FcCharSetCount (fcs_sub); if (count > 0) { FcChar32 ucs4, pos, map[FC_CHARSET_MAP_SIZE]; printf (_("%s:%d Missing %d glyph(s) to satisfy the coverage for %s language\n"), argv[i], index, count, lang); if (verbose) { for (ucs4 = FcCharSetFirstPage (fcs_sub, map, &pos); ucs4 != FC_CHARSET_DONE; ucs4 = FcCharSetNextPage (fcs_sub, map, &pos)) { int j; for (j = 0; j < FC_CHARSET_MAP_SIZE; j++) { FcChar32 bits = map[j]; FcChar32 base = ucs4 + j * 32; int b = 0; while (bits) { if (bits & 1) printf (" 0x%04x\n", base + b); bits >>= 1; b++; } } } } } else { printf (_("%s:%d Satisfy the coverage for %s language\n"), argv[i], index, lang); } FcCharSetDestroy (fcs); FcCharSetDestroy (fcs_sub); FT_Done_Face (face); } index++; } while (index_set == 0);
/* no character exists */ FcChar32 fcinfo_chars(FcCharSet *charset, FcChar32 **chars, const char *uinterval, uinterval_type_t uintype, FcBool grid, FcChar32 maxchars) { FcChar32 available, nchars, n; FcBlanks *blanks = FcConfigGetBlanks(NULL); FcChar32 ucs4; FcChar32 map[FC_CHARSET_MAP_SIZE]; FcChar32 next; int i, j, left, right; int nlines; nlines = 0; for (ucs4 = FcCharSetFirstPage (charset, map, &next); ucs4 != FC_CHARSET_DONE; ucs4 = FcCharSetNextPage (charset, map, &next)) { int i; /* for ucs4 == 0, skip i == 0 and i == 4, see below */ for (i = (ucs4 == 0 ? 1 : 0); i < FC_CHARSET_MAP_SIZE; ucs4 == 0 && i == 3 ? i = 5 : i++) if (map[i] && (!uinterval || unicode_interval_contains(uinterval, uintype, ucs4 + 32*i) || unicode_interval_contains(uinterval, uintype, ucs4 + 32*i + 0x10))) nlines++; } if (grid) available = 32*nlines; else available = FcCharSetCount(charset); nchars = available < maxchars ? available : maxchars; *chars = (FcChar32*)malloc(nchars*sizeof(FcChar32)); if (! *chars) { fprintf(stderr, "fcinfo_chars(): can't allocate memory\n"); exit(1); } /* for() code below borrowed from fontconfig-2.10.2/src/fclang.c */ n = 0; for (ucs4 = FcCharSetFirstPage (charset, map, &next); ucs4 != FC_CHARSET_DONE; ucs4 = FcCharSetNextPage (charset, map, &next)) { /* for some fonts (e. g. Dina) fontconfig reports they contain control characters; skip them for sure (we get 'wrong unicode character' while converting svg if not) */ for (i = (ucs4 == 0 ? 1 : 0); i < FC_CHARSET_MAP_SIZE; ucs4 == 0 && i == 3 ? i = 5 : i++) { if (map[i]) { left = 0; right = 32; if (uinterval && !unicode_interval_contains(uinterval, uintype, ucs4 + 32*i)) left = 16; if (uinterval && !unicode_interval_contains(uinterval, uintype, ucs4 + 32*i + 16)) right = 16; for (j = left; j < right; j++) { if (map[i] & (1 << j)) { FcChar32 ch = ucs4 + 32*i + j; if (grid == FcTrue || !FcBlanksIsMember(blanks, ch)) (*chars)[n++] = ch; } else if (grid == FcTrue) (*chars)[n++] = NO_CHAR; if (n == nchars) return n; } } } } return n; }