Merge branch 'varfonts2'
https://lists.freedesktop.org/archives/fontconfig/2017-September/006048.html
diff --git a/conf.d/90-synthetic.conf b/conf.d/90-synthetic.conf
index b8d1e85..7cd25cf 100644
--- a/conf.d/90-synthetic.conf
+++ b/conf.d/90-synthetic.conf
@@ -40,11 +40,11 @@
<match target="font">
<!-- check to see if the font is just regular -->
<test name="weight" compare="less_eq">
- <const>medium</const>
+ <const>regular</const>
</test>
<!-- check to see if the pattern requests bold -->
- <test target="pattern" name="weight" compare="more">
- <const>medium</const>
+ <test target="pattern" name="weight" compare="more_eq">
+ <const>bold</const>
</test>
<!--
set the embolden flag
diff --git a/fc-list/fc-list.c b/fc-list/fc-list.c
index f6c7282..95963e7 100644
--- a/fc-list/fc-list.c
+++ b/fc-list/fc-list.c
@@ -49,6 +49,7 @@
#include <getopt.h>
const struct option longopts[] = {
{"verbose", 0, 0, 'v'},
+ {"brief", 0, 0, 'b'},
{"format", 1, 0, 'f'},
{"quiet", 0, 0, 'q'},
{"version", 0, 0, 'V'},
@@ -67,22 +68,24 @@
{
FILE *file = error ? stderr : stdout;
#if HAVE_GETOPT_LONG
- fprintf (file, "usage: %s [-vqVh] [-f FORMAT] [--verbose] [--format=FORMAT] [--quiet] [--version] [--help] [pattern] {element ...} \n",
+ fprintf (file, "usage: %s [-vbqVh] [-f FORMAT] [--verbose] [--brief] [--format=FORMAT] [--quiet] [--version] [--help] [pattern] {element ...} \n",
program);
#else
- fprintf (file, "usage: %s [-vqVh] [-f FORMAT] [pattern] {element ...} \n",
+ fprintf (file, "usage: %s [-vbqVh] [-f FORMAT] [pattern] {element ...} \n",
program);
#endif
fprintf (file, "List fonts matching [pattern]\n");
fprintf (file, "\n");
#if HAVE_GETOPT_LONG
fprintf (file, " -v, --verbose display entire font pattern verbosely\n");
+ fprintf (file, " -b, --brief display entire font pattern briefly\n");
fprintf (file, " -f, --format=FORMAT use the given output format\n");
fprintf (file, " -q, --quiet suppress all normal output, exit 1 if no fonts matched\n");
fprintf (file, " -V, --version display font config version and exit\n");
fprintf (file, " -h, --help display this help and exit\n");
#else
fprintf (file, " -v (verbose) display entire font pattern verbosely\n");
+ fprintf (file, " -b (brief) display entire font pattern briefly\n");
fprintf (file, " -f FORMAT (format) use the given output format\n");
fprintf (file, " -q, (quiet) suppress all normal output, exit 1 if no fonts matched\n");
fprintf (file, " -V (version) display font config version and exit\n");
@@ -95,6 +98,7 @@
main (int argc, char **argv)
{
int verbose = 0;
+ int brief = 0;
int quiet = 0;
const FcChar8 *format = NULL;
int nfont = 0;
@@ -106,15 +110,18 @@
int c;
#if HAVE_GETOPT_LONG
- while ((c = getopt_long (argc, argv, "vf:qVh", longopts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "vbf:qVh", longopts, NULL)) != -1)
#else
- while ((c = getopt (argc, argv, "vf:qVh")) != -1)
+ while ((c = getopt (argc, argv, "vbf:qVh")) != -1)
#endif
{
switch (c) {
case 'v':
verbose = 1;
break;
+ case 'b':
+ brief = 1;
+ break;
case 'f':
format = (FcChar8 *) strdup (optarg);
break;
@@ -155,7 +162,7 @@
pat = FcPatternCreate ();
if (quiet && !os)
os = FcObjectSetCreate ();
- if (!verbose && !format && !os)
+ if (!verbose && !brief && !format && !os)
os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_FILE, (char *) 0);
if (!format)
format = (const FcChar8 *) "%{=fclist}\n";
@@ -171,8 +178,13 @@
for (j = 0; j < fs->nfont; j++)
{
- if (verbose)
+ if (verbose || brief)
{
+ if (brief)
+ {
+ FcPatternDel (fs->fonts[j], FC_CHARSET);
+ FcPatternDel (fs->fonts[j], FC_LANG);
+ }
FcPatternPrint (fs->fonts[j]);
}
else
diff --git a/fc-match/fc-match.c b/fc-match/fc-match.c
index f96c009..88f4ac8 100644
--- a/fc-match/fc-match.c
+++ b/fc-match/fc-match.c
@@ -52,6 +52,7 @@
{"sort", 0, 0, 's'},
{"all", 0, 0, 'a'},
{"verbose", 0, 0, 'v'},
+ {"brief", 0, 0, 'b'},
{"format", 1, 0, 'f'},
{"version", 0, 0, 'V'},
{"help", 0, 0, 'h'},
@@ -69,7 +70,7 @@
{
FILE *file = error ? stderr : stdout;
#if HAVE_GETOPT_LONG
- fprintf (file, "usage: %s [-savVh] [-f FORMAT] [--sort] [--all] [--verbose] [--format=FORMAT] [--version] [--help] [pattern] {element...}\n",
+ fprintf (file, "usage: %s [-savbVh] [-f FORMAT] [--sort] [--all] [--verbose] [--brief] [--format=FORMAT] [--version] [--help] [pattern] {element...}\n",
program);
#else
fprintf (file, "usage: %s [-savVh] [-f FORMAT] [pattern] {element...}\n",
@@ -81,6 +82,7 @@
fprintf (file, " -s, --sort display sorted list of matches\n");
fprintf (file, " -a, --all display unpruned sorted list of matches\n");
fprintf (file, " -v, --verbose display entire font pattern verbosely\n");
+ fprintf (file, " -b, --brief display entire font pattern briefly\n");
fprintf (file, " -f, --format=FORMAT use the given output format\n");
fprintf (file, " -V, --version display font config version and exit\n");
fprintf (file, " -h, --help display this help and exit\n");
@@ -88,6 +90,7 @@
fprintf (file, " -s, (sort) display sorted list of matches\n");
fprintf (file, " -a (all) display unpruned sorted list of matches\n");
fprintf (file, " -v (verbose) display entire font pattern verbosely\n");
+ fprintf (file, " -b (brief) display entire font pattern briefly\n");
fprintf (file, " -f FORMAT (format) use the given output format\n");
fprintf (file, " -V (version) display font config version and exit\n");
fprintf (file, " -h (help) display this help and exit\n");
@@ -99,6 +102,7 @@
main (int argc, char **argv)
{
int verbose = 0;
+ int brief = 0;
int sort = 0, all = 0;
const FcChar8 *format = NULL;
int i;
@@ -110,9 +114,9 @@
int c;
#if HAVE_GETOPT_LONG
- while ((c = getopt_long (argc, argv, "asvf:Vh", longopts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "asvbf:Vh", longopts, NULL)) != -1)
#else
- while ((c = getopt (argc, argv, "asvf:Vh")) != -1)
+ while ((c = getopt (argc, argv, "asvbf:Vh")) != -1)
#endif
{
switch (c) {
@@ -125,6 +129,9 @@
case 'v':
verbose = 1;
break;
+ case 'b':
+ brief = 1;
+ break;
case 'f':
format = (FcChar8 *) strdup (optarg);
break;
@@ -218,8 +225,13 @@
font = FcPatternFilter (fs->fonts[j], os);
- if (verbose)
+ if (verbose || brief)
{
+ if (brief)
+ {
+ FcPatternDel (font, FC_CHARSET);
+ FcPatternDel (font, FC_LANG);
+ }
FcPatternPrint (font);
}
else
diff --git a/fc-query/fc-query.c b/fc-query/fc-query.c
index a5b2cda..8a96da0 100644
--- a/fc-query/fc-query.c
+++ b/fc-query/fc-query.c
@@ -52,8 +52,8 @@
#define _GNU_SOURCE
#include <getopt.h>
static const struct option longopts[] = {
- {"ignore-blanks", 0, 0, 'b'},
{"index", 1, 0, 'i'},
+ {"brief", 0, 0, 'b'},
{"format", 1, 0, 'f'},
{"version", 0, 0, 'V'},
{"help", 0, 0, 'h'},
@@ -71,23 +71,23 @@
{
FILE *file = error ? stderr : stdout;
#if HAVE_GETOPT_LONG
- fprintf (file, "usage: %s [-Vbh] [-i index] [-f FORMAT] [--ignore-blanks] [--index index] [--format FORMAT] [--version] [--help] font-file...\n",
+ fprintf (file, "usage: %s [-bVh] [-i index] [-f FORMAT] [--index index] [--brief] [--format FORMAT] [--version] [--help] font-file...\n",
program);
#else
- fprintf (file, "usage: %s [-Vbh] [-i index] [-f FORMAT] font-file...\n",
+ fprintf (file, "usage: %s [-bVh] [-i index] [-f FORMAT] font-file...\n",
program);
#endif
fprintf (file, "Query font files and print resulting pattern(s)\n");
fprintf (file, "\n");
#if HAVE_GETOPT_LONG
- fprintf (file, " -b, --ignore-blanks ignore blanks to compute langauges\n");
fprintf (file, " -i, --index INDEX display the INDEX face of each font file only\n");
+ fprintf (file, " -b, --brief display font pattern briefly\n");
fprintf (file, " -f, --format=FORMAT use the given output format\n");
fprintf (file, " -V, --version display font config version and exit\n");
fprintf (file, " -h, --help display this help and exit\n");
#else
- fprintf (file, " -b (ignore-blanks) ignore blanks to compute languages\n");
fprintf (file, " -i INDEX (index) display the INDEX face of each font file only\n");
+ fprintf (file, " -b (brief) display font pattern briefly\n");
fprintf (file, " -f FORMAT (format) use the given output format\n");
fprintf (file, " -V (version) display font config version and exit\n");
fprintf (file, " -h (help) display this help and exit\n");
@@ -98,28 +98,27 @@
int
main (int argc, char **argv)
{
- int id = -1;
- int ignore_blanks = 0;
+ unsigned int id = (unsigned int) -1;
+ int brief = 0;
FcFontSet *fs;
FcChar8 *format = NULL;
- FcBlanks *blanks = NULL;
int err = 0;
int i;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
int c;
#if HAVE_GETOPT_LONG
- while ((c = getopt_long (argc, argv, "bi:f:Vh", longopts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "i:bf:Vh", longopts, NULL)) != -1)
#else
- while ((c = getopt (argc, argv, "bi:f:Vh")) != -1)
+ while ((c = getopt (argc, argv, "i:bf:Vh")) != -1)
#endif
{
switch (c) {
- case 'b':
- ignore_blanks = 1;
- break;
case 'i':
- id = atoi (optarg);
+ id = (unsigned int) strtol (optarg, NULL, 0); /* strtol() To handle -1. */
+ break;
+ case 'b':
+ brief = 1;
break;
case 'f':
format = (FcChar8 *) strdup (optarg);
@@ -143,14 +142,12 @@
usage (argv[0], 1);
fs = FcFontSetCreate ();
- if (!ignore_blanks)
- blanks = FcConfigGetBlanks (NULL);
for (; i < argc; i++)
{
- if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, blanks, NULL, fs))
+ if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, NULL, NULL, fs))
{
- fprintf (stderr, "Can't query face %d of font file %s\n", id, argv[i]);
+ fprintf (stderr, "Can't query face %u of font file %s\n", id, argv[i]);
err = 1;
}
}
@@ -159,6 +156,12 @@
{
FcPattern *pat = fs->fonts[i];
+ if (brief)
+ {
+ FcPatternDel (pat, FC_CHARSET);
+ FcPatternDel (pat, FC_LANG);
+ }
+
if (format)
{
FcChar8 *s;
diff --git a/fc-scan/fc-scan.c b/fc-scan/fc-scan.c
index 58a0b15..41bd260 100644
--- a/fc-scan/fc-scan.c
+++ b/fc-scan/fc-scan.c
@@ -52,6 +52,7 @@
#define _GNU_SOURCE
#include <getopt.h>
static const struct option longopts[] = {
+ {"brief", 0, 0, 'b'},
{"format", 1, 0, 'f'},
{"version", 0, 0, 'V'},
{"help", 0, 0, 'h'},
@@ -69,19 +70,21 @@
{
FILE *file = error ? stderr : stdout;
#if HAVE_GETOPT_LONG
- fprintf (file, "usage: %s [-Vh] [-f FORMAT] [--format FORMAT] [--version] [--help] font-file...\n",
+ fprintf (file, "usage: %s [-bVh] [-f FORMAT] [--brief] [--format FORMAT] [--version] [--help] font-file...\n",
program);
#else
- fprintf (file, "usage: %s [-Vh] [-f FORMAT] font-file...\n",
+ fprintf (file, "usage: %s [-bVh] [-f FORMAT] font-file...\n",
program);
#endif
fprintf (file, "Scan font files and directories, and print resulting pattern(s)\n");
fprintf (file, "\n");
#if HAVE_GETOPT_LONG
+ fprintf (file, " -b, --brief display font pattern briefly\n");
fprintf (file, " -f, --format=FORMAT use the given output format\n");
fprintf (file, " -V, --version display font config version and exit\n");
fprintf (file, " -h, --help display this help and exit\n");
#else
+ fprintf (file, " -b (brief) display font pattern briefly\n");
fprintf (file, " -f FORMAT (format) use the given output format\n");
fprintf (file, " -V (version) display font config version and exit\n");
fprintf (file, " -h (help) display this help and exit\n");
@@ -92,6 +95,7 @@
int
main (int argc, char **argv)
{
+ int brief = 0;
FcChar8 *format = NULL;
int i;
FcFontSet *fs;
@@ -105,6 +109,9 @@
#endif
{
switch (c) {
+ case 'b':
+ brief = 1;
+ break;
case 'f':
format = (FcChar8 *) strdup (optarg);
break;
@@ -152,6 +159,12 @@
{
FcPattern *pat = fs->fonts[i];
+ if (brief)
+ {
+ FcPatternDel (pat, FC_CHARSET);
+ FcPatternDel (pat, FC_LANG);
+ }
+
if (format)
{
FcChar8 *s;
diff --git a/fontconfig/fcfreetype.h b/fontconfig/fcfreetype.h
index 753fdf9..20b1128 100644
--- a/fontconfig/fcfreetype.h
+++ b/fontconfig/fcfreetype.h
@@ -51,7 +51,7 @@
FcPublic FcPattern *
FcFreeTypeQueryFace (const FT_Face face,
const FcChar8 *file,
- int id,
+ unsigned int id,
FcBlanks *blanks);
_FCFUNCPROTOEND
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index f085aa0..0f4dcb9 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -72,8 +72,9 @@
#define _FC_STRINGIFY(s) _FC_STRINGIFY_(s)
#define FC_CACHE_VERSION _FC_STRINGIFY(FC_CACHE_VERSION_NUMBER)
-#define FcTrue 1
#define FcFalse 0
+#define FcTrue 1
+#define FcDontCare 2
#define FC_FAMILY "family" /* String */
#define FC_STYLE "style" /* String */
@@ -99,6 +100,7 @@
#define FC_OUTLINE "outline" /* Bool */
#define FC_SCALABLE "scalable" /* Bool */
#define FC_COLOR "color" /* Bool */
+#define FC_VARIABLE "variable" /* Bool */
#define FC_SCALE "scale" /* double (deprecated) */
#define FC_SYMBOL "symbol" /* Bool */
#define FC_DPI "dpi" /* double */
@@ -119,6 +121,7 @@
#define FC_DECORATIVE "decorative" /* Bool - true if style is a decorative variant */
#define FC_LCD_FILTER "lcdfilter" /* Int */
#define FC_FONT_FEATURES "fontfeatures" /* String */
+#define FC_FONT_VARIATIONS "fontvariations" /* String */
#define FC_NAMELANG "namelang" /* String RFC 3866 langs */
#define FC_PRGNAME "prgname" /* String */
#define FC_HASH "hash" /* String (deprecated) */
@@ -575,10 +578,10 @@
/* fcfreetype.c */
FcPublic FcPattern *
-FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count);
+FcFreeTypeQuery (const FcChar8 *file, unsigned int id, FcBlanks *blanks, int *count);
FcPublic unsigned int
-FcFreeTypeQueryAll(const FcChar8 *file, int id, FcBlanks *blanks, int *count, FcFontSet *set);
+FcFreeTypeQueryAll(const FcChar8 *file, unsigned int id, FcBlanks *blanks, int *count, FcFontSet *set);
/* fcfs.c */
diff --git a/src/fccfg.c b/src/fccfg.c
index 4f38af1..4b22d48 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -796,14 +796,30 @@
case FcTypeBool:
switch ((int) op) {
case FcOpEqual:
- case FcOpContains:
- case FcOpListing:
ret = left.u.b == right.u.b;
break;
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.b == right.u.b || left.u.b == FcDontCare;
+ break;
case FcOpNotEqual:
- case FcOpNotContains:
ret = left.u.b != right.u.b;
break;
+ case FcOpNotContains:
+ ret = !(left.u.b == right.u.b || left.u.b == FcDontCare);
+ break;
+ case FcOpLess:
+ ret = left.u.b != right.u.b && right.u.b == FcDontCare;
+ break;
+ case FcOpLessEqual:
+ ret = left.u.b == right.u.b || right.u.b == FcDontCare;
+ break;
+ case FcOpMore:
+ ret = left.u.b != right.u.b && left.u.b == FcDontCare;
+ break;
+ case FcOpMoreEqual:
+ ret = left.u.b == right.u.b || left.u.b == FcDontCare;
+ break;
default:
break;
}
diff --git a/src/fcdbg.c b/src/fcdbg.c
index c2853ff..29ff44a 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -46,7 +46,10 @@
fprintf (f, "\"%s\"", v.u.s);
break;
case FcTypeBool:
- fprintf (f, "%s", v.u.b ? "True" : "False");
+ fprintf (f,
+ v.u.b == FcTrue ? (FcChar8 *) "True" :
+ v.u.b == FcFalse ? (FcChar8 *) "False" :
+ (FcChar8 *) "DontCare", 0);
break;
case FcTypeMatrix:
fprintf (f, "[%g %g; %g %g]", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
@@ -62,7 +65,7 @@
fprintf (f, "face");
break;
case FcTypeRange:
- fprintf (f, "[%g %g)", v.u.r->begin, v.u.r->end);
+ fprintf (f, "[%g %g]", v.u.r->begin, v.u.r->end);
break;
}
}
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 5afd7ec..35973d7 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -39,6 +39,7 @@
{ FC_EMBEDDED_BITMAP_OBJECT, FcTrue }, /* !FC_LOAD_NO_BITMAP */
{ FC_DECORATIVE_OBJECT, FcFalse },
{ FC_SYMBOL_OBJECT, FcFalse },
+ { FC_VARIABLE_OBJECT, FcFalse },
};
#define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
@@ -255,7 +256,14 @@
FcPatternObjectAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value);
if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch)
- size = 12.0L;
+ {
+ FcRange *r;
+ double b, e;
+ if (FcPatternObjectGetRange (pattern, FC_SIZE_OBJECT, 0, &r) == FcResultMatch && FcRangeGetDouble (r, &b, &e))
+ size = (b + e) * .5;
+ else
+ size = 12.0L;
+ }
if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch)
scale = 1.0;
if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch)
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index a6e7058..cddd3a1 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -558,6 +558,9 @@
static FcChar8 *
FcFontCapabilities(FT_Face face);
+static int
+FcFreeTypeSpacing (FT_Face face);
+
#define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
@@ -1133,6 +1136,7 @@
TT_PLATFORM_MICROSOFT,
TT_PLATFORM_APPLE_UNICODE,
TT_PLATFORM_MACINTOSH,
+ TT_PLATFORM_ISO,
};
#define NUM_PLATFORM_ORDER (sizeof (platform_order) / sizeof (platform_order[0]))
@@ -1154,19 +1158,51 @@
};
#define NUM_NAMEID_ORDER (sizeof (nameid_order) / sizeof (nameid_order[0]))
-FcPattern *
-FcFreeTypeQueryFace (const FT_Face face,
- const FcChar8 *file,
- int id,
- FcBlanks *blanks FC_UNUSED)
+
+static FcBool
+FcFreeTypeGetName (const FT_Face face,
+ unsigned int platform,
+ unsigned int nameid,
+ FT_SfntName *sname)
+{
+ int min = 0, max = (int) FT_Get_Sfnt_Name_Count (face) - 1;
+
+ while (min <= max)
+ {
+ int mid = (min + max) / 2;
+
+ if (FT_Get_Sfnt_Name (face, mid, sname) != 0)
+ return FcFalse;
+
+ if (platform < sname->platform_id || (platform == sname->platform_id && nameid < sname->name_id))
+ max = mid - 1;
+ else if (platform > sname->platform_id || (platform == sname->platform_id && nameid > sname->name_id))
+ min = mid + 1;
+ else
+ return FcTrue;
+ }
+
+ return FcFalse;
+}
+
+static FcPattern *
+FcFreeTypeQueryFaceInternal (const FT_Face face,
+ const FcChar8 *file,
+ unsigned int id,
+ FcCharSet **cs_share,
+ FcLangSet **ls_share)
{
FcPattern *pat;
int slant = -1;
int weight = -1;
int width = -1;
FcBool decorative = FcFalse;
- FcCharSet *cs;
- FcLangSet *ls;
+ FcBool variable = FcFalse;
+ FcBool variable_weight = FcFalse;
+ FcBool variable_width = FcFalse;
+ FcBool variable_size = FcFalse;
+ FcCharSet *cs;
+ FcLangSet *ls;
#if 0
FcChar8 *family = 0;
#endif
@@ -1189,8 +1225,6 @@
#endif
TT_Header *head;
const FcChar8 *exclusiveLang = 0;
- FT_SfntName sname;
- FT_UInt snamei, snamec;
int nfamily = 0;
int nfamily_lang = 0;
@@ -1199,14 +1233,9 @@
int nfullname = 0;
int nfullname_lang = 0;
unsigned int p, n;
- int platform, nameid;
FcChar8 *style = 0;
int st;
- char psname[256];
- const char *tmp;
-
- FcRange *r = NULL;
FcBool symbol = FcFalse;
@@ -1238,35 +1267,101 @@
if (id >> 16)
{
- if (!FT_Get_MM_Var (face, &master))
- instance = &master->namedstyle[(id >> 16) - 1];
+ if (FT_Get_MM_Var (face, &master))
+ goto bail1;
- if (instance)
+ if (id >> 16 == 0x8000)
{
- /* Pull out weight and width from named-instance. */
+ /* Query variable font itself. */
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;
+ double min_value = master->axis[i].minimum / (double) (1 << 16);
+ double def_value = master->axis[i].def / (double) (1 << 16);
+ double max_value = master->axis[i].maximum / (double) (1 << 16);
+ const char *elt = NULL;
- case FT_MAKE_TAG ('w','d','t','h'):
- width_mult = mult;
- break;
+ if (min_value > def_value || def_value > max_value || min_value == max_value)
+ continue;
- /* TODO optical size! */
+ switch (master->axis[i].tag)
+ {
+ case FT_MAKE_TAG ('w','g','h','t'):
+ elt = FC_WEIGHT;
+ min_value = FcWeightFromOpenType (min_value);
+ max_value = FcWeightFromOpenType (max_value);
+ variable_weight = FcTrue;
+ weight = 0; /* To stop looking for weight. */
+ break;
+
+ case FT_MAKE_TAG ('w','d','t','h'):
+ elt = FC_WIDTH;
+ /* Values in 'wdth' match Fontconfig FC_WIDTH_* scheme directly. */
+ variable_width = FcTrue;
+ width = 0; /* To stop looking for width. */
+ break;
+
+ case FT_MAKE_TAG ('o','p','s','z'):
+ elt = FC_SIZE;
+ /* Values in 'opsz' match Fontconfig FC_SIZE, both are in points. */
+ variable_size = FcTrue;
+ break;
+ }
+
+ if (elt)
+ {
+ FcRange *r = FcRangeCreateDouble (min_value, max_value);
+ if (!FcPatternAddRange (pat, elt, r))
+ {
+ FcRangeDestroy (r);
+ goto bail1;
+ }
+ FcRangeDestroy (r);
+ variable = FcTrue;
+ }
+ }
+
+ if (!variable)
+ goto bail1;
+
+ id &= 0xFFFF;
+ }
+ else if ((id >> 16) - 1 < master->num_namedstyles)
+ {
+ /* Pull out weight and width from named-instance. */
+ unsigned int i;
+
+ instance = &master->namedstyle[(id >> 16) - 1];
+
+ 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 = default_value ? value / default_value : 1;
+ //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;
+
+ case FT_MAKE_TAG ('o','p','s','z'):
+ if (!FcPatternAddDouble (pat, FC_SIZE, value))
+ goto bail1;
+ break;
}
}
}
+ else
+ goto bail1;
}
+ if (!FcPatternAddBool (pat, FC_VARIABLE, variable))
+ goto bail1;
/*
* Get the OS/2 table
@@ -1299,13 +1394,9 @@
* and style names. FreeType makes quite a hash
* of them
*/
- snamec = FT_Get_Sfnt_Name_Count (face);
- for (p = 0; p <= NUM_PLATFORM_ORDER; p++)
+ for (p = 0; p < NUM_PLATFORM_ORDER; p++)
{
- if (p < NUM_PLATFORM_ORDER)
- platform = platform_order[p];
- else
- platform = 0xffff;
+ int platform = platform_order[p];
/*
* Order nameids so preferred names appear first
@@ -1313,159 +1404,142 @@
*/
for (n = 0; n < NUM_NAMEID_ORDER; n++)
{
- nameid = nameid_order[n];
+ FT_SfntName sname;
+ const FcChar8 *lang;
+ const char *elt = 0, *eltlang = 0;
+ int *np = 0, *nlangp = 0;
+ size_t len;
+ int nameid, lookupid;
- for (snamei = 0; snamei < snamec; snamei++)
+ nameid = lookupid = nameid_order[n];
+
+ if (instance)
+ {
+ /* For named-instances, we skip regular style nameIDs,
+ * and treat the instance's nameid as FONT_SUBFAMILY.
+ * Postscript name is automatically handled by FreeType. */
+ if (nameid == TT_NAME_ID_WWS_SUBFAMILY ||
+ nameid == TT_NAME_ID_PREFERRED_SUBFAMILY)
+ continue;
+
+ if (nameid == TT_NAME_ID_FONT_SUBFAMILY)
+ lookupid = instance->strid;
+ }
+
+ if (!FcFreeTypeGetName (face, platform, lookupid, &sname))
+ continue;
+
+ switch (nameid) {
+#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_UNIQUE_ID:
+#endif
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("found family (n %2d p %d e %d l 0x%04x)",
+ sname.name_id, sname.platform_id,
+ sname.encoding_id, sname.language_id);
+
+ 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)",
+ sname.name_id, sname.platform_id,
+ sname.encoding_id, sname.language_id);
+
+ 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 (variable)
+ break;
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("found style (n %2d p %d e %d l 0x%04x) ",
+ sname.name_id, sname.platform_id,
+ sname.encoding_id, sname.language_id);
+
+ 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)
+ {
+ FcChar8 *utf8;
+ utf8 = FcSfntNameTranscode (&sname);
+ foundry = FcNoticeFoundry((FT_String *) utf8);
+ free (utf8);
+ }
+ break;
+ }
+ if (elt)
{
FcChar8 *utf8, *pp;
- const FcChar8 *lang;
- const char *elt = 0, *eltlang = 0;
- int *np = 0, *nlangp = 0;
- size_t len;
- 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;
-
- /*
- * Sort platforms in preference order, accepting
- * all other platforms last
- */
- if (p < NUM_PLATFORM_ORDER)
- {
- if (sname.platform_id != platform)
- continue;
- }
- else
- {
- unsigned 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 (FcDebug () & FC_DBG_SCANV)
+ printf ("%s\n", utf8);
+
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_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);
+ /* Trim surrounding whitespace. */
+ pp = utf8;
+ while (*pp == ' ')
+ pp++;
+ len = strlen ((const char *) pp);
+ memmove (utf8, pp, len + 1);
+ pp = utf8 + len;
+ while (pp > utf8 && *(pp - 1) == ' ')
+ pp--;
+ *pp = 0;
- 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 (utf8)
- {
- pp = utf8;
- while (*pp == ' ')
- pp++;
- len = strlen ((const char *) pp);
- memmove (utf8, pp, len + 1);
- pp = utf8 + len - 1;
- while (*pp == ' ')
- pp--;
- *(pp + 1) = 0;
- }
- 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 (FcStringInPatternElement (pat, elt, utf8))
{
- if (FcStringInPatternElement (pat, elt, utf8))
- {
- free (utf8);
- continue;
- }
-
- /* add new element */
- if (!FcPatternAddString (pat, elt, utf8))
- {
- free (utf8);
- goto bail1;
- }
free (utf8);
- if (lang)
+ continue;
+ }
+
+ /* add new element */
+ if (!FcPatternAddString (pat, elt, utf8))
+ {
+ free (utf8);
+ goto bail1;
+ }
+ free (utf8);
+ if (lang)
+ {
+ /* pad lang list with 'und' to line up with elt */
+ while (*nlangp < *np)
{
- /* pad lang list with 'und' to line up with elt */
- while (*nlangp < *np)
- {
- if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
- goto bail1;
- ++*nlangp;
- }
- if (!FcPatternAddString (pat, eltlang, lang))
+ if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
goto bail1;
++*nlangp;
}
- ++*np;
+ if (!FcPatternAddString (pat, eltlang, lang))
+ goto bail1;
+ ++*nlangp;
}
- else
- free (utf8);
+ ++*np;
}
}
}
@@ -1482,11 +1556,12 @@
++nfamily;
}
- if (!nstyle && face->style_name &&
+ if (!variable && !nstyle && face->style_name &&
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, (FcChar8 *) face->style_name))
goto bail1;
if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en"))
@@ -1523,52 +1598,57 @@
}
/* Add the PostScript name into the cache */
- tmp = FT_Get_Postscript_Name (face);
- if (!tmp)
+ if (!variable)
{
- unsigned int i;
- FcChar8 *family, *familylang = NULL;
- size_t len;
- int n = 0;
-
- /* Workaround when FT_Get_Postscript_Name didn't give any name.
- * try to find out the English family name and convert.
- */
- while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
+ char psname[256];
+ const char *tmp;
+ tmp = FT_Get_Postscript_Name (face);
+ if (!tmp)
{
- if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
- break;
- n++;
- familylang = NULL;
- }
- if (!familylang)
- n = 0;
+ unsigned int i;
+ FcChar8 *family, *familylang = NULL;
+ size_t len;
+ int n = 0;
- if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
+ /* Workaround when FT_Get_Postscript_Name didn't give any name.
+ * try to find out the English family name and convert.
+ */
+ while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
+ {
+ if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
+ break;
+ n++;
+ familylang = NULL;
+ }
+ if (!familylang)
+ n = 0;
+
+ if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
+ goto bail1;
+ len = strlen ((const char *)family);
+ /* the literal name in PostScript Language is limited to 127 characters though,
+ * It is the architectural limit. so assuming 255 characters may works enough.
+ */
+ for (i = 0; i < len && i < 255; i++)
+ {
+ /* those characters are not allowed to be the literal name in PostScript */
+ static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
+
+ if (strchr(exclusive_chars, family[i]) != NULL)
+ psname[i] = '-';
+ else
+ psname[i] = family[i];
+ }
+ psname[i] = 0;
+ }
+ else
+ {
+ strncpy (psname, tmp, 255);
+ psname[255] = 0;
+ }
+ if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
goto bail1;
- len = strlen ((const char *)family);
- /* the literal name in PostScript Language is limited to 127 characters though,
- * It is the architectural limit. so assuming 255 characters may works enough.
- */
- for (i = 0; i < len && i < 255; i++)
- {
- /* those characters are not allowed to be the literal name in PostScript */
- static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
-
- if (strchr(exclusive_chars, family[i]) != NULL)
- psname[i] = '-';
- else
- psname[i] = family[i];
- }
- psname[i] = 0;
}
- else
- {
- strncpy (psname, tmp, 255);
- psname[255] = 0;
- }
- if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
- goto bail1;
if (file && *file && !FcPatternAddString (pat, FC_FILE, file))
goto bail1;
@@ -1679,21 +1759,30 @@
}
#if defined (HAVE_TT_OS2_USUPPEROPTICALPOINTSIZE) && defined (HAVE_TT_OS2_USLOWEROPTICALPOINTSIZE)
- if (os2 && os2->version >= 0x0005 && os2->version != 0xffff)
+ if (!variable_size && os2 && os2->version >= 0x0005 && os2->version != 0xffff)
{
double lower_size, upper_size;
+ FcRange *r;
/* 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))
+ if (lower_size == upper_size)
{
- FcRangeDestroy (r);
- goto bail1;
+ if (!FcPatternAddDouble (pat, FC_SIZE, lower_size))
+ goto bail1;
}
- FcRangeDestroy (r);
+ else
+ {
+ r = FcRangeCreateDouble (lower_size, upper_size);
+ if (!FcPatternAddRange (pat, FC_SIZE, r))
+ {
+ FcRangeDestroy (r);
+ goto bail1;
+ }
+ FcRangeDestroy (r);
+ }
}
#endif
@@ -1835,10 +1924,10 @@
if (!FcPatternAddInteger (pat, FC_SLANT, slant))
goto bail1;
- if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
+ if (!variable_weight && !FcPatternAddInteger (pat, FC_WEIGHT, weight))
goto bail1;
- if (!FcPatternAddInteger (pat, FC_WIDTH, width))
+ if (!variable_width && !FcPatternAddInteger (pat, FC_WIDTH, width))
goto bail1;
if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
@@ -1851,15 +1940,23 @@
/*
* Compute the unicode coverage for the font
*/
- cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+ if (cs_share && *cs_share)
+ cs = FcCharSetCopy (*cs_share);
+ else
+ {
+ cs = FcFreeTypeCharSet (face, NULL);
+ if (cs_share)
+ *cs_share = FcCharSetCopy (cs);
+ }
if (!cs)
goto bail1;
- /* The FcFreeTypeCharSetAndSpacing() chose the encoding; test it for symbol. */
+ /* The FcFreeTypeCharSet() 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;
+ spacing = FcFreeTypeSpacing (face);
#if HAVE_FT_GET_BDF_PROPERTY
/* For PCF fonts, override the computed spacing with the one from
the property */
@@ -1894,7 +1991,14 @@
if (!symbol)
{
- ls = FcFreeTypeLangSet (cs, exclusiveLang);
+ if (ls_share && *ls_share)
+ ls = FcLangSetCopy (*ls_share);
+ else
+ {
+ ls = FcFreeTypeLangSet (cs, exclusiveLang);
+ if (ls_share)
+ *ls_share = FcLangSetCopy (ls);
+ }
if (!ls)
goto bail2;
}
@@ -1965,9 +2069,18 @@
}
FcPattern *
+FcFreeTypeQueryFace (const FT_Face face,
+ const FcChar8 *file,
+ unsigned int id,
+ FcBlanks *blanks FC_UNUSED)
+{
+ return FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL);
+}
+
+FcPattern *
FcFreeTypeQuery(const FcChar8 *file,
- int id,
- FcBlanks *blanks,
+ unsigned int id,
+ FcBlanks *blanks FC_UNUSED,
int *count)
{
FT_Face face;
@@ -1977,13 +2090,13 @@
if (FT_Init_FreeType (&ftLibrary))
return NULL;
- if (FT_New_Face (ftLibrary, (char *) file, id, &face))
+ if (FT_New_Face (ftLibrary, (char *) file, id & 0x7FFFFFFFF, &face))
goto bail;
if (count)
*count = face->num_faces;
- pat = FcFreeTypeQueryFace (face, file, id, blanks);
+ pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL);
FT_Done_Face (face);
bail:
@@ -1993,59 +2106,112 @@
unsigned int
FcFreeTypeQueryAll(const FcChar8 *file,
- int id,
+ unsigned int id,
FcBlanks *blanks,
int *count,
FcFontSet *set)
{
- FT_Face face;
+ FT_Face face = NULL;
FT_Library ftLibrary = NULL;
- int index_set = id != -1;
- int set_face_num = index_set ? id & 0xFFFF : 0;
- int set_instance_num = index_set ? id >> 16 : 0;
- int face_num = set_face_num;
- int instance_num = set_instance_num;
- int num_faces = 0;
- int num_instances = 0;
+ FcCharSet *cs = NULL;
+ FcLangSet *ls = NULL;
+ FT_MM_Var *mm_var = NULL;
+ FcBool index_set = id != (unsigned int) -1;
+ unsigned int set_face_num = index_set ? id & 0xFFFF : 0;
+ unsigned int set_instance_num = index_set ? id >> 16 : 0;
+ unsigned int face_num = set_face_num;
+ unsigned int instance_num = set_instance_num;
+ unsigned int num_faces = 0;
+ unsigned int num_instances = 0;
unsigned int ret = 0;
- int err = 0;
+ int err = 0;
+
+ if (count)
+ *count = 0;
if (FT_Init_FreeType (&ftLibrary))
return 0;
- do {
- FcPattern *pat;
+ if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
+ goto bail;
- id = ((instance_num << 16) + face_num);
- if (FT_New_Face (ftLibrary, (const char *) file, id, &face))
- break;
-
- num_faces = face->num_faces;
- num_instances = face->style_flags >> 16;
- pat = FcFreeTypeQueryFace (face, (const FcChar8 *) file, id, blanks);
- FT_Done_Face (face);
-
- if (pat)
- {
- ret++;
- if (!set || ! FcFontSetAdd (set, pat))
- FcPatternDestroy (pat);
- }
- else
- err = 1;
-
- if (instance_num < num_instances && !set_instance_num)
- instance_num++;
- else
- {
- face_num++;
- instance_num = 0;
- }
- } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
+ num_faces = face->num_faces;
+ num_instances = face->style_flags >> 16;
+ if (num_instances && (!index_set || instance_num))
+ {
+ FT_Get_MM_Var (face, &mm_var);
+ assert (mm_var);
+ }
if (count)
*count = num_faces;
+ do {
+ FcPattern *pat = NULL;
+
+ if (instance_num == 0x8000 || instance_num > num_instances)
+ FT_Set_Var_Design_Coordinates (face, 0, NULL); /* Reset variations. */
+ else if (instance_num)
+ {
+ FT_Var_Named_Style *instance = &mm_var->namedstyle[instance_num - 1];
+ FT_Fixed *coords = instance->coords;
+ FcBool nonzero;
+ unsigned int i;
+
+ /* Skip named-instance that coincides with base instance. */
+ nonzero = FcFalse;
+ for (i = 0; i < mm_var->num_axis; i++)
+ if (coords[i] != mm_var->axis[i].def)
+ {
+ nonzero = FcTrue;
+ break;
+ }
+ if (!nonzero)
+ goto skip;
+
+ FT_Set_Var_Design_Coordinates (face, mm_var->num_axis, coords);
+ }
+
+ id = ((instance_num << 16) + face_num);
+ pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, &cs, &ls);
+
+ if (pat)
+ {
+
+ ret++;
+ if (!set || ! FcFontSetAdd (set, pat))
+ FcPatternDestroy (pat);
+ }
+ else if (instance_num != 0x8000)
+ err = 1;
+
+skip:
+ if (!index_set && instance_num < num_instances)
+ instance_num++;
+ else if (!index_set && instance_num == num_instances)
+ instance_num = 0x8000; /* variable font */
+ else
+ {
+ FcLangSetDestroy (ls);
+ ls = NULL;
+ FcCharSetDestroy (cs);
+ cs = NULL;
+ FT_Done_Face (face);
+ face = NULL;
+
+ face_num++;
+ instance_num = set_instance_num;
+
+ if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
+ break;
+ }
+ } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
+
+bail:
+ FcLangSetDestroy (ls);
+ FcCharSetDestroy (cs);
+ if (face)
+ FT_Done_Face (face);
FT_Done_FreeType (ftLibrary);
return ret;
@@ -2134,18 +2300,13 @@
static inline FcBool fc_approximately_equal (int x, int y)
{ return abs (x - y) * 33 <= fc_max (abs (x), abs (y)); }
-FcCharSet *
-FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
+static int
+FcFreeTypeSpacing (FT_Face face)
{
- FcCharSet *fcs;
- int o;
FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
- FT_Pos advances[3];
+ FT_Pos advances[3] = {};
unsigned int num_advances = 0;
-
- fcs = FcCharSetCreate ();
- if (!fcs)
- goto bail0;
+ int o;
/* When using scalable fonts, only report those glyphs
* which can be scaled; otherwise those fonts will
@@ -2170,18 +2331,65 @@
strike_index = i;
}
- if (FT_Select_Size (face, strike_index) != FT_Err_Ok)
- goto bail1;
+ FT_Select_Size (face, strike_index);
}
#endif
+ for (o = 0; o < NUM_DECODE; o++)
+ {
+ FcChar32 ucs4;
+ FT_UInt glyph;
+
+ if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
+ continue;
+
+ ucs4 = FT_Get_First_Char (face, &glyph);
+ while (glyph != 0 && num_advances < 3)
+ {
+ FT_Pos advance = 0;
+ if (!FT_Get_Advance (face, glyph, load_flags, &advance) && advance)
+ {
+ unsigned int j;
+ for (j = 0; j < num_advances; j++)
+ if (fc_approximately_equal (advance, advances[j]))
+ break;
+ if (j == num_advances)
+ advances[num_advances++] = advance;
+ }
+
+ ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
+ }
+ break;
+ }
+
+ if (num_advances <= 1)
+ return FC_MONO;
+ else if (num_advances == 2 &&
+ fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
+ fc_max (advances[0], advances[1])))
+ return FC_DUAL;
+ else
+ return FC_PROPORTIONAL;
+}
+
+FcCharSet *
+FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
+{
+ const FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+ FcCharSet *fcs;
+ int o;
+
+ fcs = FcCharSetCreate ();
+ if (!fcs)
+ goto bail;
+
#ifdef CHECK
printf ("Family %s style %s\n", face->family_name, face->style_name);
#endif
for (o = 0; o < NUM_DECODE; o++)
{
- FcChar32 page, off, ucs4;
- FcCharLeaf *leaf;
+ FcChar32 page, off, ucs4;
+ FcCharLeaf *leaf;
FT_UInt glyph;
if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
@@ -2206,26 +2414,13 @@
if (good)
{
- if (num_advances < 3)
- {
- FT_Pos advance = 0;
- if (!FT_Get_Advance (face, glyph, load_flags, &advance) && advance)
- {
- unsigned int i;
- for (i = 0; i < num_advances; i++)
- if (fc_approximately_equal (advance, advances[i]))
- break;
- if (i == num_advances)
- advances[num_advances++] = advance;
- }
- }
-
+ FcCharSetAddChar (fcs, ucs4);
if ((ucs4 >> 8) != page)
{
page = (ucs4 >> 8);
leaf = FcCharSetFindLeafCreate (fcs, ucs4);
if (!leaf)
- goto bail1;
+ goto bail;
}
off = ucs4 & 0xff;
leaf->map[off >> 5] |= (1 << (off & 0x1f));
@@ -2265,27 +2460,21 @@
#endif
break;
}
- if (num_advances <= 1)
- *spacing = FC_MONO;
- else if (num_advances == 2 &&
- fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
- fc_max (advances[0], advances[1])))
- *spacing = FC_DUAL;
- else
- *spacing = FC_PROPORTIONAL;
+
return fcs;
-bail1:
+bail:
FcCharSetDestroy (fcs);
-bail0:
return 0;
}
FcCharSet *
-FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
+FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
{
- int spacing;
- return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+ if (spacing)
+ *spacing = FcFreeTypeSpacing (face);
+
+ return FcFreeTypeCharSet (face, blanks);
}
diff --git a/src/fclang.c b/src/fclang.c
index 107addb..eadf34b 100644
--- a/src/fclang.c
+++ b/src/fclang.c
@@ -485,6 +485,9 @@
void
FcLangSetDestroy (FcLangSet *ls)
{
+ if (!ls)
+ return;
+
if (ls->extra)
FcStrSetDestroy (ls->extra);
free (ls);
@@ -495,6 +498,9 @@
{
FcLangSet *new;
+ if (!ls)
+ return NULL;
+
new = FcLangSetCreate ();
if (!new)
goto bail0;
diff --git a/src/fcmatch.c b/src/fcmatch.c
index 40efbd3..d5eaea7 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -25,7 +25,7 @@
#include "fcint.h"
static double
-FcCompareNumber (FcValue *value1, FcValue *value2)
+FcCompareNumber (const FcValue *value1, const FcValue *value2, FcValue *bestValue)
{
double v1, v2, v;
@@ -52,23 +52,27 @@
v = v2 - v1;
if (v < 0)
v = -v;
+ *bestValue = FcValueCanonicalize (value2);
return v;
}
static double
-FcCompareString (FcValue *v1, FcValue *v2)
+FcCompareString (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
+ *bestValue = FcValueCanonicalize (v2);
return (double) FcStrCmpIgnoreCase (FcValueString(v1), FcValueString(v2)) != 0;
}
static double
-FcCompareFamily (FcValue *v1, FcValue *v2)
+FcCompareFamily (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
/* rely on the guarantee in FcPatternObjectAddWithBinding that
* families are always FcTypeString. */
const FcChar8* v1_string = FcValueString(v1);
const FcChar8* v2_string = FcValueString(v2);
+ *bestValue = FcValueCanonicalize (v2);
+
if (FcToLower(*v1_string) != FcToLower(*v2_string) &&
*v1_string != ' ' && *v2_string != ' ')
return 1.0;
@@ -77,13 +81,15 @@
}
static double
-FcComparePostScript (FcValue *v1, FcValue *v2)
+FcComparePostScript (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
const FcChar8 *v1_string = FcValueString (v1);
const FcChar8 *v2_string = FcValueString (v2);
int n;
size_t len;
+ *bestValue = FcValueCanonicalize (v2);
+
if (FcToLower (*v1_string) != FcToLower (*v2_string) &&
*v1_string != ' ' && *v2_string != ' ')
return 1.0;
@@ -95,7 +101,7 @@
}
static double
-FcCompareLang (FcValue *v1, FcValue *v2)
+FcCompareLang (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
FcLangResult result;
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
@@ -130,6 +136,7 @@
default:
return -1.0;
}
+ *bestValue = FcValueCanonicalize (v2);
switch (result) {
case FcLangEqual:
return 0;
@@ -142,99 +149,134 @@
}
static double
-FcCompareBool (FcValue *v1, FcValue *v2)
+FcCompareBool (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
if (v2->type != FcTypeBool || v1->type != FcTypeBool)
return -1.0;
- return (double) v2->u.b != v1->u.b;
+
+ if (v2->u.b != FcDontCare)
+ *bestValue = FcValueCanonicalize (v2);
+ else
+ *bestValue = FcValueCanonicalize (v1);
+
+ return (double) ((v2->u.b ^ v1->u.b) == 1);
}
static double
-FcCompareCharSet (FcValue *v1, FcValue *v2)
+FcCompareCharSet (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
+ *bestValue = FcValueCanonicalize (v2); /* TODO Improve. */
return (double) FcCharSetSubtractCount (FcValueCharSet(v1), FcValueCharSet(v2));
}
static double
-FcCompareSize (FcValue *value1, FcValue *value2)
-{
- double v1, v2, v;
-
- switch ((int) value1->type) {
- case FcTypeInteger:
- v1 = value1->u.i;
- break;
- case FcTypeDouble:
- v1 = value1->u.d;
- break;
- default:
- return -1;
- }
- switch ((int) value2->type) {
- case FcTypeInteger:
- v2 = value2->u.i;
- break;
- case FcTypeDouble:
- v2 = value2->u.d;
- break;
- default:
- return -1;
- }
- if (v2 == 0)
- return 0;
- v = v2 - v1;
- if (v < 0)
- v = -v;
- return v;
-}
-
-static double
-FcCompareSizeRange (FcValue *v1, FcValue *v2)
+FcCompareRange (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
FcValue value1 = FcValueCanonicalize (v1);
FcValue value2 = FcValueCanonicalize (v2);
- FcRange *r1 = NULL, *r2 = NULL;
- double ret = -1.0;
+ double b1, e1, b2, e2, d;
switch ((int) value1.type) {
+ case FcTypeInteger:
+ b1 = e1 = value1.u.i;
+ break;
case FcTypeDouble:
- r1 = FcRangeCreateDouble (value1.u.d, value1.u.d);
+ b1 = e1 = value1.u.d;
break;
case FcTypeRange:
- r1 = FcRangeCopy (value1.u.r);
+ abort();
+ b1 = value1.u.r->begin;
+ e1 = value1.u.r->end;
break;
default:
- goto bail;
+ return -1;
}
switch ((int) value2.type) {
+ case FcTypeInteger:
+ b2 = e2 = value2.u.i;
+ break;
case FcTypeDouble:
- r2 = FcRangeCreateDouble (value2.u.d, value2.u.d);
+ b2 = e2 = value2.u.d;
break;
case FcTypeRange:
- r2 = FcRangeCopy (value2.u.r);
+ b2 = value2.u.r->begin;
+ e2 = value2.u.r->end;
break;
default:
- goto bail;
+ return -1;
}
- if (FcRangeIsInRange (r1, r2))
- ret = 0.0;
+ if (e1 < b2)
+ d = b2;
+ else if (e2 < b1)
+ d = e2;
else
- ret = FC_MIN (fabs (r1->end - r2->begin), fabs (r1->begin - r2->end));
+ d = (FC_MAX (b1, b2) + FC_MIN (e1, e2)) * .5;
-bail:
- if (r1)
- FcRangeDestroy (r1);
- if (r2)
- FcRangeDestroy (r2);
+ bestValue->type = FcTypeDouble;
+ bestValue->u.d = d;
- return ret;
+ /* If the ranges overlap, it's a match, otherwise return closest distance. */
+ if (e1 < b2 || e2 < b1)
+ return FC_MIN (fabs (b2 - e1), fabs (b1 - e2));
+ else
+ return 0.0;
}
static double
-FcCompareFilename (FcValue *v1, FcValue *v2)
+FcCompareSize (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
+{
+ FcValue value1 = FcValueCanonicalize (v1);
+ FcValue value2 = FcValueCanonicalize (v2);
+ double b1, e1, b2, e2;
+
+ switch ((int) value1.type) {
+ case FcTypeInteger:
+ b1 = e1 = value1.u.i;
+ break;
+ case FcTypeDouble:
+ b1 = e1 = value1.u.d;
+ break;
+ case FcTypeRange:
+ abort();
+ b1 = value1.u.r->begin;
+ e1 = value1.u.r->end;
+ break;
+ default:
+ return -1;
+ }
+ switch ((int) value2.type) {
+ case FcTypeInteger:
+ b2 = e2 = value2.u.i;
+ break;
+ case FcTypeDouble:
+ b2 = e2 = value2.u.d;
+ break;
+ case FcTypeRange:
+ b2 = value2.u.r->begin;
+ e2 = value2.u.r->end;
+ break;
+ default:
+ return -1;
+ }
+
+ bestValue->type = FcTypeDouble;
+ bestValue->u.d = (b1 + e1) * .5;
+
+ /* If the ranges overlap, it's a match, otherwise return closest distance. */
+ if (e1 < b2 || e2 < b1)
+ return FC_MIN (fabs (b2 - e1), fabs (b1 - e2));
+ if (b2 != e2 && b1 == e2) /* Semi-closed interval. */
+ return 1e-15;
+ else
+ return 0.0;
+}
+
+static double
+FcCompareFilename (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
{
const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
+ *bestValue = FcValueCanonicalize (v2);
if (FcStrCmp (s1, s2) == 0)
return 0.0;
else if (FcStrCmpIgnoreCase (s1, s2) == 0)
@@ -255,13 +297,13 @@
#define PRI_FcCompareFamily(n) PRI1(n)
#define PRI_FcCompareString(n) PRI1(n)
#define PRI_FcCompareNumber(n) PRI1(n)
-#define PRI_FcCompareSize(n) PRI1(n)
#define PRI_FcCompareBool(n) PRI1(n)
#define PRI_FcCompareFilename(n) PRI1(n)
#define PRI_FcCompareCharSet(n) PRI1(n)
#define PRI_FcCompareLang(n) PRI1(n)
#define PRI_FcComparePostScript(n) PRI1(n)
-#define PRI_FcCompareSizeRange(n) PRI1(n)
+#define PRI_FcCompareRange(n) PRI1(n)
+#define PRI_FcCompareSize(n) PRI1(n)
#define FC_OBJECT(NAME, Type, Cmp) PRI_##Cmp(NAME)
@@ -283,6 +325,7 @@
typedef enum _FcMatcherPriority {
PRI1(FILE),
PRI1(FONTFORMAT),
+ PRI1(VARIABLE),
PRI1(SCALABLE),
PRI1(COLOR),
PRI1(FOUNDRY),
@@ -312,7 +355,7 @@
typedef struct _FcMatcher {
FcObject object;
- double (*compare) (FcValue *value1, FcValue *value2);
+ double (*compare) (const FcValue *v1, const FcValue *v2, FcValue *bestValue);
int strong, weak;
} FcMatcher;
@@ -382,7 +425,8 @@
{
for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++)
{
- v = (match->compare) (&v1->value, &v2->value);
+ FcValue matchValue;
+ v = (match->compare) (&v1->value, &v2->value, &matchValue);
if (v < 0)
{
*result = FcResultTypeMismatch;
@@ -392,7 +436,7 @@
if (v < best)
{
if (bestValue)
- *bestValue = FcValueCanonicalize(&v2->value);
+ *bestValue = matchValue;
best = v;
pos = k;
}
@@ -1017,7 +1061,8 @@
FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
{
- double compare = FcCompareLang (&patternLang, &nodeLang);
+ FcValue matchValue;
+ double compare = FcCompareLang (&patternLang, &nodeLang, &matchValue);
if (compare >= 0 && compare < 2)
{
if (FcDebug () & FC_DBG_MATCHV)
diff --git a/src/fcname.c b/src/fcname.c
index 8be36c7..79e413e 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -258,6 +258,11 @@
*result = FcFalse;
return FcTrue;
}
+ if (c0 == 'd' || c0 == 'x' || c0 == '2')
+ {
+ *result = FcDontCare;
+ return FcTrue;
+ }
if (c0 == 'o')
{
c1 = v[1];
@@ -272,6 +277,11 @@
*result = FcFalse;
return FcTrue;
}
+ if (c1 == 'r')
+ {
+ *result = FcDontCare;
+ return FcTrue;
+ }
}
return FcFalse;
}
@@ -318,7 +328,7 @@
v.type = FcTypeVoid;
break;
case FcTypeRange:
- if (sscanf ((char *) string, "[%lg %lg)", &b, &e) != 2)
+ if (sscanf ((char *) string, "[%lg %lg]", &b, &e) != 2)
{
v.u.d = strtod ((char *) string, &p);
if (p != NULL && p[0] != 0)
@@ -514,7 +524,10 @@
case FcTypeString:
return FcNameUnparseString (buf, v.u.s, escape);
case FcTypeBool:
- return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
+ return FcNameUnparseString (buf,
+ v.u.b == FcTrue ? (FcChar8 *) "True" :
+ v.u.b == FcFalse ? (FcChar8 *) "False" :
+ (FcChar8 *) "DontCare", 0);
case FcTypeMatrix:
sprintf ((char *) temp, "%g %g %g %g",
v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
@@ -526,7 +539,7 @@
case FcTypeFTFace:
return FcTrue;
case FcTypeRange:
- sprintf ((char *) temp, "[%g %g)", v.u.r->begin, v.u.r->end);
+ sprintf ((char *) temp, "[%g %g]", v.u.r->begin, v.u.r->end);
return FcNameUnparseString (buf, temp, 0);
}
return FcFalse;
diff --git a/src/fcobjs.h b/src/fcobjs.h
index d27864b..e3926cc 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -29,11 +29,11 @@
FC_OBJECT (FULLNAME, FcTypeString, NULL)
FC_OBJECT (FULLNAMELANG, FcTypeString, NULL)
FC_OBJECT (SLANT, FcTypeInteger, FcCompareNumber)
-FC_OBJECT (WEIGHT, FcTypeInteger, FcCompareNumber)
-FC_OBJECT (WIDTH, FcTypeInteger, FcCompareNumber)
-FC_OBJECT (SIZE, FcTypeRange, FcCompareSizeRange)
+FC_OBJECT (WEIGHT, FcTypeRange, FcCompareRange)
+FC_OBJECT (WIDTH, FcTypeRange, FcCompareRange)
+FC_OBJECT (SIZE, FcTypeRange, FcCompareSize)
FC_OBJECT (ASPECT, FcTypeDouble, NULL)
-FC_OBJECT (PIXEL_SIZE, FcTypeDouble, FcCompareSize)
+FC_OBJECT (PIXEL_SIZE, FcTypeDouble, FcCompareNumber)
FC_OBJECT (SPACING, FcTypeInteger, FcCompareNumber)
FC_OBJECT (FOUNDRY, FcTypeString, FcCompareString)
FC_OBJECT (ANTIALIAS, FcTypeBool, FcCompareBool)
@@ -70,4 +70,6 @@
FC_OBJECT (POSTSCRIPT_NAME, FcTypeString, FcComparePostScript)
FC_OBJECT (COLOR, FcTypeBool, FcCompareBool)
FC_OBJECT (SYMBOL, FcTypeBool, FcCompareBool)
+FC_OBJECT (FONT_VARIATIONS, FcTypeString, NULL)
+FC_OBJECT (VARIABLE, FcTypeBool, FcCompareBool)
/* ^-------------- Add new objects here. */
diff --git a/src/fcpat.c b/src/fcpat.c
index cc303c6..dd1307d 100644
--- a/src/fcpat.c
+++ b/src/fcpat.c
@@ -1113,6 +1113,9 @@
int i;
FcValueListPtr l;
+ if (!orig)
+ return NULL;
+
new = FcPatternCreate ();
if (!new)
goto bail0;
diff --git a/src/fcrange.c b/src/fcrange.c
index f70226c..8689930 100644
--- a/src/fcrange.c
+++ b/src/fcrange.c
@@ -96,9 +96,6 @@
FcBool
FcRangeIsInRange (const FcRange *a, const FcRange *b)
{
- if (!a || !b)
- return FcFalse;
-
return a->begin >= b->begin && a->end <= b->end;
}
@@ -107,20 +104,22 @@
{
switch ((int) op) {
case FcOpEqual:
+ return a->begin == b->begin && a->end == b->end;
case FcOpContains:
case FcOpListing:
return FcRangeIsInRange (a, b);
case FcOpNotEqual:
+ return a->begin != b->begin || a->end != b->end;
case FcOpNotContains:
return !FcRangeIsInRange (a, b);
case FcOpLess:
- return a->begin < b->begin;
+ return a->end < b->begin;
case FcOpLessEqual:
- return a->begin <= b->begin;
+ return a->end <= b->begin;
case FcOpMore:
- return a->end > b->end;
+ return a->begin > b->end;
case FcOpMoreEqual:
- return a->end >= b->end;
+ return a->begin >= b->end;
default:
break;
}