[varfonts] Query varfonts if id >> 16 == 0x8000
If "instance-number" part of face id is set to 0x8000, return a pattern
for variable font as a whole. This might have a range for weight, width,
and size.
If no variation is found, NULL is returned.
Not hooked up to FcQueryFaceAll() yet. For now, can be triggered using
fc-query -i 0x80000000
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index caca5d9..de05aa6 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1165,6 +1165,10 @@
int weight = -1;
int width = -1;
FcBool decorative = FcFalse;
+ FcBool variable = FcFalse;
+ FcBool variable_weight = FcFalse;
+ FcBool variable_width = FcFalse;
+ FcBool variable_size = FcFalse;
FcCharSet *cs;
FcLangSet *ls;
#if 0
@@ -1206,8 +1210,6 @@
char psname[256];
const char *tmp;
- FcRange *r = NULL;
-
FcBool symbol = FcFalse;
FcInitDebug (); /* We might be called with no initizalization whatsoever. */
@@ -1236,20 +1238,70 @@
goto bail1;
}
- if (!FcPatternAddBool (pat, FC_VARIABLE, FcFalse))
- goto bail1;
-
if (id >> 16)
{
- unsigned int instance_id = (id >> 16) - 1;
- if (!FT_Get_MM_Var (face, &master) && instance_id < master->num_namedstyles)
- instance = &master->namedstyle[instance_id];
+ if (FT_Get_MM_Var (face, &master))
+ goto bail1;
- if (instance)
+ if (id >> 16 == 0x8000)
+ {
+ /* Query variable font itself. */
+ unsigned int i;
+
+ for (i = 0; i < master->num_axis; i++)
+ {
+ 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;
+
+ if (min_value > def_value || def_value > max_value || min_value == max_value)
+ continue;
+
+ switch (master->axis[i].tag)
+ {
+ case FT_MAKE_TAG ('w','g','h','t'):
+ elt = FC_WEIGHT;
+ variable = variable_weight = FcTrue;
+ weight = 0; /* To stop looking for weight. */
+ break;
+
+ case FT_MAKE_TAG ('w','d','t','h'):
+ elt = FC_WIDTH;
+ variable = variable_width = FcTrue;
+ width = 0; /* To stop looking for width. */
+ break;
+
+ case FT_MAKE_TAG ('o','p','s','z'):
+ elt = FC_SIZE;
+ variable = variable_size = FcTrue;
+ break;
+ }
+
+ if (elt)
+ {
+ FcRange *r = FcRangeCreateDouble (min_value, max_value);
+ if (!FcPatternAddRange (pat, elt, r))
+ {
+ FcRangeDestroy (r);
+ goto bail1;
+ }
+ FcRangeDestroy (r);
+ }
+ }
+
+ 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);
@@ -1273,6 +1325,8 @@
else
goto bail1;
}
+ if (!FcPatternAddBool (pat, FC_VARIABLE, variable))
+ goto bail1;
/*
* Get the OS/2 table
@@ -1685,9 +1739,10 @@
}
#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;
@@ -1841,10 +1896,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))
@@ -1983,7 +2038,7 @@
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)
@@ -2023,7 +2078,7 @@
FcPattern *pat;
id = ((instance_num << 16) + face_num);
- if (FT_New_Face (ftLibrary, (const char *) file, id, &face))
+ if (FT_New_Face (ftLibrary, (const char *) file, id & 0x7FFFFFFF, &face))
break;
num_faces = face->num_faces;