In RenderPrepare(), handle ranges smartly
If font claims to support range [100,900], and request is for [250], then return [250] in "rendered" pattern. Previously was returning [100,900]. This is desirable for varfonts weight and width, but probably not for size. Will roll back size to return request size always, for non-empty ranges.
This commit is contained in:
parent
6a13a21e40
commit
2db7ca7d58
|
@ -25,7 +25,7 @@
|
||||||
#include "fcint.h"
|
#include "fcint.h"
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcCompareNumber (FcValue *value1, FcValue *value2)
|
FcCompareNumber (const FcValue *value1, const FcValue *value2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
double v1, v2, v;
|
double v1, v2, v;
|
||||||
|
|
||||||
|
@ -52,23 +52,27 @@ FcCompareNumber (FcValue *value1, FcValue *value2)
|
||||||
v = v2 - v1;
|
v = v2 - v1;
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
v = -v;
|
v = -v;
|
||||||
|
*bestValue = FcValueCanonicalize (value2);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
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;
|
return (double) FcStrCmpIgnoreCase (FcValueString(v1), FcValueString(v2)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcCompareFamily (FcValue *v1, FcValue *v2)
|
FcCompareFamily (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
/* rely on the guarantee in FcPatternObjectAddWithBinding that
|
/* rely on the guarantee in FcPatternObjectAddWithBinding that
|
||||||
* families are always FcTypeString. */
|
* families are always FcTypeString. */
|
||||||
const FcChar8* v1_string = FcValueString(v1);
|
const FcChar8* v1_string = FcValueString(v1);
|
||||||
const FcChar8* v2_string = FcValueString(v2);
|
const FcChar8* v2_string = FcValueString(v2);
|
||||||
|
|
||||||
|
*bestValue = FcValueCanonicalize (v2);
|
||||||
|
|
||||||
if (FcToLower(*v1_string) != FcToLower(*v2_string) &&
|
if (FcToLower(*v1_string) != FcToLower(*v2_string) &&
|
||||||
*v1_string != ' ' && *v2_string != ' ')
|
*v1_string != ' ' && *v2_string != ' ')
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
@ -77,13 +81,15 @@ FcCompareFamily (FcValue *v1, FcValue *v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcComparePostScript (FcValue *v1, FcValue *v2)
|
FcComparePostScript (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
const FcChar8 *v1_string = FcValueString (v1);
|
const FcChar8 *v1_string = FcValueString (v1);
|
||||||
const FcChar8 *v2_string = FcValueString (v2);
|
const FcChar8 *v2_string = FcValueString (v2);
|
||||||
int n;
|
int n;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
|
*bestValue = FcValueCanonicalize (v2);
|
||||||
|
|
||||||
if (FcToLower (*v1_string) != FcToLower (*v2_string) &&
|
if (FcToLower (*v1_string) != FcToLower (*v2_string) &&
|
||||||
*v1_string != ' ' && *v2_string != ' ')
|
*v1_string != ' ' && *v2_string != ' ')
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
@ -95,7 +101,7 @@ FcComparePostScript (FcValue *v1, FcValue *v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcCompareLang (FcValue *v1, FcValue *v2)
|
FcCompareLang (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
FcLangResult result;
|
FcLangResult result;
|
||||||
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
|
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
|
||||||
|
@ -130,6 +136,7 @@ FcCompareLang (FcValue *v1, FcValue *v2)
|
||||||
default:
|
default:
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
|
*bestValue = FcValueCanonicalize (v2);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case FcLangEqual:
|
case FcLangEqual:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -142,25 +149,28 @@ FcCompareLang (FcValue *v1, FcValue *v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcCompareBool (FcValue *v1, FcValue *v2)
|
FcCompareBool (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
if (v2->type != FcTypeBool || v1->type != FcTypeBool)
|
if (v2->type != FcTypeBool || v1->type != FcTypeBool)
|
||||||
return -1.0;
|
return -1.0;
|
||||||
|
|
||||||
|
*bestValue = FcValueCanonicalize (v2);
|
||||||
return (double) v2->u.b != v1->u.b;
|
return (double) v2->u.b != v1->u.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
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));
|
return (double) FcCharSetSubtractCount (FcValueCharSet(v1), FcValueCharSet(v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcCompareRange (FcValue *v1, FcValue *v2)
|
FcCompareRange (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
FcValue value1 = FcValueCanonicalize (v1);
|
FcValue value1 = FcValueCanonicalize (v1);
|
||||||
FcValue value2 = FcValueCanonicalize (v2);
|
FcValue value2 = FcValueCanonicalize (v2);
|
||||||
double b1, e1, b2, e2;
|
double b1, e1, b2, e2, d;
|
||||||
|
|
||||||
switch ((int) value1.type) {
|
switch ((int) value1.type) {
|
||||||
case FcTypeInteger:
|
case FcTypeInteger:
|
||||||
|
@ -192,6 +202,16 @@ FcCompareRange (FcValue *v1, FcValue *v2)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e1 < b2)
|
||||||
|
d = b2;
|
||||||
|
else if (e2 < b1)
|
||||||
|
d = e2;
|
||||||
|
else
|
||||||
|
d = (FC_MAX (b1, b2) + FC_MIN (e1, e2)) * .5;
|
||||||
|
|
||||||
|
bestValue->type = FcTypeDouble;
|
||||||
|
bestValue->u.d = d;
|
||||||
|
|
||||||
/* If the ranges overlap, it's a match, otherwise return closest distance. */
|
/* If the ranges overlap, it's a match, otherwise return closest distance. */
|
||||||
if (e1 < b2 || e2 < b1)
|
if (e1 < b2 || e2 < b1)
|
||||||
return FC_MIN (fabs (b2 - e1), fabs (b1 - e2));
|
return FC_MIN (fabs (b2 - e1), fabs (b1 - e2));
|
||||||
|
@ -200,9 +220,10 @@ FcCompareRange (FcValue *v1, FcValue *v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
FcCompareFilename (FcValue *v1, FcValue *v2)
|
FcCompareFilename (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
|
||||||
{
|
{
|
||||||
const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
|
const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
|
||||||
|
*bestValue = FcValueCanonicalize (v2);
|
||||||
if (FcStrCmp (s1, s2) == 0)
|
if (FcStrCmp (s1, s2) == 0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
else if (FcStrCmpIgnoreCase (s1, s2) == 0)
|
else if (FcStrCmpIgnoreCase (s1, s2) == 0)
|
||||||
|
@ -280,7 +301,7 @@ typedef enum _FcMatcherPriority {
|
||||||
|
|
||||||
typedef struct _FcMatcher {
|
typedef struct _FcMatcher {
|
||||||
FcObject object;
|
FcObject object;
|
||||||
double (*compare) (FcValue *value1, FcValue *value2);
|
double (*compare) (const FcValue *v1, const FcValue *v2, FcValue *bestValue);
|
||||||
int strong, weak;
|
int strong, weak;
|
||||||
} FcMatcher;
|
} FcMatcher;
|
||||||
|
|
||||||
|
@ -350,7 +371,8 @@ FcCompareValueList (FcObject object,
|
||||||
{
|
{
|
||||||
for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++)
|
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)
|
if (v < 0)
|
||||||
{
|
{
|
||||||
*result = FcResultTypeMismatch;
|
*result = FcResultTypeMismatch;
|
||||||
|
@ -360,7 +382,7 @@ FcCompareValueList (FcObject object,
|
||||||
if (v < best)
|
if (v < best)
|
||||||
{
|
{
|
||||||
if (bestValue)
|
if (bestValue)
|
||||||
*bestValue = FcValueCanonicalize(&v2->value);
|
*bestValue = matchValue;
|
||||||
best = v;
|
best = v;
|
||||||
pos = k;
|
pos = k;
|
||||||
}
|
}
|
||||||
|
@ -985,7 +1007,8 @@ FcFontSetSort (FcConfig *config FC_UNUSED,
|
||||||
FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
|
FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
|
||||||
FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == 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 (compare >= 0 && compare < 2)
|
||||||
{
|
{
|
||||||
if (FcDebug () & FC_DBG_MATCHV)
|
if (FcDebug () & FC_DBG_MATCHV)
|
||||||
|
|
Loading…
Reference in New Issue