зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1533428 - patch 5 - Move the helper functions that measure the 'distance' between values of font properties (weight, stretch, style) to gfxFontUtils.h. r=jwatt
This will allow upcoming shared font-list to use the same helpers as the existing code. Differential Revision: https://phabricator.services.mozilla.com/D22926 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
f5e8791f61
Коммит
27e809db53
|
@ -1246,250 +1246,13 @@ gfxFontEntry* gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// style distance ==> [0,500]
|
||||
static inline double StyleDistance(const gfxFontEntry* aFontEntry,
|
||||
FontSlantStyle aTargetStyle) {
|
||||
const FontSlantStyle minStyle = aFontEntry->SlantStyle().Min();
|
||||
if (aTargetStyle == minStyle) {
|
||||
return 0.0; // styles match exactly ==> 0
|
||||
}
|
||||
|
||||
// bias added to angle difference when searching in the non-preferred
|
||||
// direction from a target angle
|
||||
const double kReverse = 100.0;
|
||||
|
||||
// bias added when we've crossed from positive to negative angles or
|
||||
// vice versa
|
||||
const double kNegate = 200.0;
|
||||
|
||||
if (aTargetStyle.IsNormal()) {
|
||||
if (minStyle.IsOblique()) {
|
||||
// to distinguish oblique 0deg from normal, we add 1.0 to the angle
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle >= 0.0) {
|
||||
return 1.0 + minAngle;
|
||||
}
|
||||
const FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= 0.0) {
|
||||
// [min,max] range includes 0.0, so just return our minimum
|
||||
return 1.0;
|
||||
}
|
||||
// negative oblique is even worse than italic
|
||||
return kNegate - maxAngle;
|
||||
}
|
||||
// must be italic, which is worse than any non-negative oblique;
|
||||
// treat as a match in the wrong search direction
|
||||
MOZ_ASSERT(minStyle.IsItalic());
|
||||
return kReverse;
|
||||
}
|
||||
|
||||
const double kDefaultAngle = FontSlantStyle::Oblique().ObliqueAngle();
|
||||
|
||||
if (aTargetStyle.IsItalic()) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle >= kDefaultAngle) {
|
||||
return 1.0 + (minAngle - kDefaultAngle);
|
||||
}
|
||||
const FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= kDefaultAngle) {
|
||||
return 1.0;
|
||||
}
|
||||
if (maxAngle > 0.0) {
|
||||
// wrong direction but still > 0, add bias of 100
|
||||
return kReverse + (kDefaultAngle - maxAngle);
|
||||
}
|
||||
// negative oblique angle, add bias of 300
|
||||
return kReverse + kNegate + (kDefaultAngle - maxAngle);
|
||||
}
|
||||
// normal is worse than oblique > 0, but better than oblique <= 0
|
||||
MOZ_ASSERT(minStyle.IsNormal());
|
||||
return kNegate;
|
||||
}
|
||||
|
||||
// target is oblique <angle>: four different cases depending on
|
||||
// the value of the <angle>, which determines the preferred direction
|
||||
// of search
|
||||
const double targetAngle = aTargetStyle.ObliqueAngle();
|
||||
if (targetAngle >= kDefaultAngle) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle >= targetAngle) {
|
||||
return minAngle - targetAngle;
|
||||
}
|
||||
const FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (maxAngle > 0.0) {
|
||||
return kReverse + (targetAngle - maxAngle);
|
||||
}
|
||||
return kReverse + kNegate + (targetAngle - maxAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate;
|
||||
}
|
||||
return kReverse + kNegate + 1.0;
|
||||
}
|
||||
|
||||
if (targetAngle <= -kDefaultAngle) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle <= targetAngle) {
|
||||
return targetAngle - maxAngle;
|
||||
}
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle <= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (minAngle < 0.0) {
|
||||
return kReverse + (minAngle - targetAngle);
|
||||
}
|
||||
return kReverse + kNegate + (minAngle - targetAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate;
|
||||
}
|
||||
return kReverse + kNegate + 1.0;
|
||||
}
|
||||
|
||||
if (targetAngle >= 0.0) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle > targetAngle) {
|
||||
return kReverse + (minAngle - targetAngle);
|
||||
}
|
||||
const FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (maxAngle > 0.0) {
|
||||
return targetAngle - maxAngle;
|
||||
}
|
||||
return kReverse + kNegate + (targetAngle - maxAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate - 2.0;
|
||||
}
|
||||
return kReverse + kNegate - 1.0;
|
||||
}
|
||||
|
||||
// last case: (targetAngle < 0.0 && targetAngle > kDefaultAngle)
|
||||
if (minStyle.IsOblique()) {
|
||||
const FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle < targetAngle) {
|
||||
return kReverse + (targetAngle - maxAngle);
|
||||
}
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle <= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (minAngle < 0.0) {
|
||||
return minAngle - targetAngle;
|
||||
}
|
||||
return kReverse + kNegate + (minAngle - targetAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate - 2.0;
|
||||
}
|
||||
return kReverse + kNegate - 1.0;
|
||||
}
|
||||
|
||||
// stretch distance ==> [0,2000]
|
||||
static inline double StretchDistance(const gfxFontEntry* aFontEntry,
|
||||
FontStretch aTargetStretch) {
|
||||
const double kReverseDistance = 1000.0;
|
||||
|
||||
FontStretch minStretch = aFontEntry->Stretch().Min();
|
||||
FontStretch maxStretch = aFontEntry->Stretch().Max();
|
||||
|
||||
// The stretch value is a (non-negative) percentage; currently we support
|
||||
// values in the range 0 .. 1000. (If the upper limit is ever increased,
|
||||
// the kReverseDistance value used here may need to be adjusted.)
|
||||
// If aTargetStretch is >100, we prefer larger values if available;
|
||||
// if <=100, we prefer smaller values if available.
|
||||
if (aTargetStretch < minStretch) {
|
||||
if (aTargetStretch > FontStretch::Normal()) {
|
||||
return minStretch - aTargetStretch;
|
||||
}
|
||||
return (minStretch - aTargetStretch) + kReverseDistance;
|
||||
}
|
||||
if (aTargetStretch > maxStretch) {
|
||||
if (aTargetStretch <= FontStretch::Normal()) {
|
||||
return aTargetStretch - maxStretch;
|
||||
}
|
||||
return (aTargetStretch - maxStretch) + kReverseDistance;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Calculate weight distance with values in the range (0..1000). In general,
|
||||
// heavier weights match towards even heavier weights while lighter weights
|
||||
// match towards even lighter weights. Target weight values in the range
|
||||
// [400..500] are special, since they will first match up to 500, then down
|
||||
// towards 0, then up again towards 999.
|
||||
//
|
||||
// Example: with target 600 and font weight 800, distance will be 200. With
|
||||
// target 300 and font weight 600, distance will be 900, since heavier
|
||||
// weights are farther away than lighter weights. If the target is 5 and the
|
||||
// font weight 995, the distance would be 1590 for the same reason.
|
||||
|
||||
// weight distance ==> [0,1600]
|
||||
static inline double WeightDistance(const gfxFontEntry* aFontEntry,
|
||||
FontWeight aTargetWeight) {
|
||||
const double kNotWithinCentralRange = 100.0;
|
||||
const double kReverseDistance = 600.0;
|
||||
|
||||
FontWeight minWeight = aFontEntry->Weight().Min();
|
||||
FontWeight maxWeight = aFontEntry->Weight().Max();
|
||||
|
||||
if (aTargetWeight >= minWeight && aTargetWeight <= maxWeight) {
|
||||
// Target is within the face's range, so it's a perfect match
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (aTargetWeight < FontWeight(400)) {
|
||||
// Requested a lighter-than-400 weight
|
||||
if (maxWeight < aTargetWeight) {
|
||||
return aTargetWeight - maxWeight;
|
||||
}
|
||||
// Add reverse-search penalty for bolder faces
|
||||
return (minWeight - aTargetWeight) + kReverseDistance;
|
||||
}
|
||||
|
||||
if (aTargetWeight > FontWeight(500)) {
|
||||
// Requested a bolder-than-500 weight
|
||||
if (minWeight > aTargetWeight) {
|
||||
return minWeight - aTargetWeight;
|
||||
}
|
||||
// Add reverse-search penalty for lighter faces
|
||||
return (aTargetWeight - maxWeight) + kReverseDistance;
|
||||
}
|
||||
|
||||
// Special case for requested weight in the [400..500] range
|
||||
if (minWeight > aTargetWeight) {
|
||||
if (minWeight <= FontWeight(500)) {
|
||||
// Bolder weight up to 500 is first choice
|
||||
return minWeight - aTargetWeight;
|
||||
}
|
||||
// Other bolder weights get a reverse-search penalty
|
||||
return (minWeight - aTargetWeight) + kReverseDistance;
|
||||
}
|
||||
// Lighter weights are not as good as bolder ones within [400..500]
|
||||
return (aTargetWeight - maxWeight) + kNotWithinCentralRange;
|
||||
}
|
||||
|
||||
static inline double WeightStyleStretchDistance(
|
||||
gfxFontEntry* aFontEntry, const gfxFontStyle& aTargetStyle) {
|
||||
double stretchDist = StretchDistance(aFontEntry, aTargetStyle.stretch);
|
||||
double styleDist = StyleDistance(aFontEntry, aTargetStyle.style);
|
||||
double weightDist = WeightDistance(aFontEntry, aTargetStyle.weight);
|
||||
double stretchDist =
|
||||
StretchDistance(aFontEntry->Stretch(), aTargetStyle.stretch);
|
||||
double styleDist =
|
||||
StyleDistance(aFontEntry->SlantStyle(), aTargetStyle.style);
|
||||
double weightDist = WeightDistance(aFontEntry->Weight(), aTargetStyle.weight);
|
||||
|
||||
// Sanity-check that the distances are within the expected range
|
||||
// (update if implementation of the distance functions is changed).
|
||||
|
|
|
@ -992,4 +992,244 @@ class gfxFontUtils {
|
|||
static const mozilla::Encoding* gMSFontNameCharsets[];
|
||||
};
|
||||
|
||||
// style distance ==> [0,500]
|
||||
static inline double StyleDistance(const mozilla::SlantStyleRange& aRange,
|
||||
mozilla::FontSlantStyle aTargetStyle) {
|
||||
const mozilla::FontSlantStyle minStyle = aRange.Min();
|
||||
if (aTargetStyle == minStyle) {
|
||||
return 0.0; // styles match exactly ==> 0
|
||||
}
|
||||
|
||||
// bias added to angle difference when searching in the non-preferred
|
||||
// direction from a target angle
|
||||
const double kReverse = 100.0;
|
||||
|
||||
// bias added when we've crossed from positive to negative angles or
|
||||
// vice versa
|
||||
const double kNegate = 200.0;
|
||||
|
||||
if (aTargetStyle.IsNormal()) {
|
||||
if (minStyle.IsOblique()) {
|
||||
// to distinguish oblique 0deg from normal, we add 1.0 to the angle
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle >= 0.0) {
|
||||
return 1.0 + minAngle;
|
||||
}
|
||||
const mozilla::FontSlantStyle maxStyle = aRange.Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= 0.0) {
|
||||
// [min,max] range includes 0.0, so just return our minimum
|
||||
return 1.0;
|
||||
}
|
||||
// negative oblique is even worse than italic
|
||||
return kNegate - maxAngle;
|
||||
}
|
||||
// must be italic, which is worse than any non-negative oblique;
|
||||
// treat as a match in the wrong search direction
|
||||
MOZ_ASSERT(minStyle.IsItalic());
|
||||
return kReverse;
|
||||
}
|
||||
|
||||
const double kDefaultAngle =
|
||||
mozilla::FontSlantStyle::Oblique().ObliqueAngle();
|
||||
|
||||
if (aTargetStyle.IsItalic()) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle >= kDefaultAngle) {
|
||||
return 1.0 + (minAngle - kDefaultAngle);
|
||||
}
|
||||
const mozilla::FontSlantStyle maxStyle = aRange.Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= kDefaultAngle) {
|
||||
return 1.0;
|
||||
}
|
||||
if (maxAngle > 0.0) {
|
||||
// wrong direction but still > 0, add bias of 100
|
||||
return kReverse + (kDefaultAngle - maxAngle);
|
||||
}
|
||||
// negative oblique angle, add bias of 300
|
||||
return kReverse + kNegate + (kDefaultAngle - maxAngle);
|
||||
}
|
||||
// normal is worse than oblique > 0, but better than oblique <= 0
|
||||
MOZ_ASSERT(minStyle.IsNormal());
|
||||
return kNegate;
|
||||
}
|
||||
|
||||
// target is oblique <angle>: four different cases depending on
|
||||
// the value of the <angle>, which determines the preferred direction
|
||||
// of search
|
||||
const double targetAngle = aTargetStyle.ObliqueAngle();
|
||||
if (targetAngle >= kDefaultAngle) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle >= targetAngle) {
|
||||
return minAngle - targetAngle;
|
||||
}
|
||||
const mozilla::FontSlantStyle maxStyle = aRange.Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (maxAngle > 0.0) {
|
||||
return kReverse + (targetAngle - maxAngle);
|
||||
}
|
||||
return kReverse + kNegate + (targetAngle - maxAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate;
|
||||
}
|
||||
return kReverse + kNegate + 1.0;
|
||||
}
|
||||
|
||||
if (targetAngle <= -kDefaultAngle) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const mozilla::FontSlantStyle maxStyle = aRange.Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle <= targetAngle) {
|
||||
return targetAngle - maxAngle;
|
||||
}
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle <= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (minAngle < 0.0) {
|
||||
return kReverse + (minAngle - targetAngle);
|
||||
}
|
||||
return kReverse + kNegate + (minAngle - targetAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate;
|
||||
}
|
||||
return kReverse + kNegate + 1.0;
|
||||
}
|
||||
|
||||
if (targetAngle >= 0.0) {
|
||||
if (minStyle.IsOblique()) {
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle > targetAngle) {
|
||||
return kReverse + (minAngle - targetAngle);
|
||||
}
|
||||
const mozilla::FontSlantStyle maxStyle = aRange.Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle >= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (maxAngle > 0.0) {
|
||||
return targetAngle - maxAngle;
|
||||
}
|
||||
return kReverse + kNegate + (targetAngle - maxAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate - 2.0;
|
||||
}
|
||||
return kReverse + kNegate - 1.0;
|
||||
}
|
||||
|
||||
// last case: (targetAngle < 0.0 && targetAngle > kDefaultAngle)
|
||||
if (minStyle.IsOblique()) {
|
||||
const mozilla::FontSlantStyle maxStyle = aRange.Max();
|
||||
const double maxAngle = maxStyle.ObliqueAngle();
|
||||
if (maxAngle < targetAngle) {
|
||||
return kReverse + (targetAngle - maxAngle);
|
||||
}
|
||||
const double minAngle = minStyle.ObliqueAngle();
|
||||
if (minAngle <= targetAngle) {
|
||||
return 0.0;
|
||||
}
|
||||
if (minAngle < 0.0) {
|
||||
return minAngle - targetAngle;
|
||||
}
|
||||
return kReverse + kNegate + (minAngle - targetAngle);
|
||||
}
|
||||
if (minStyle.IsItalic()) {
|
||||
return kReverse + kNegate - 2.0;
|
||||
}
|
||||
return kReverse + kNegate - 1.0;
|
||||
}
|
||||
|
||||
// stretch distance ==> [0,2000]
|
||||
static inline double StretchDistance(const mozilla::StretchRange& aRange,
|
||||
mozilla::FontStretch aTargetStretch) {
|
||||
const double kReverseDistance = 1000.0;
|
||||
|
||||
mozilla::FontStretch minStretch = aRange.Min();
|
||||
mozilla::FontStretch maxStretch = aRange.Max();
|
||||
|
||||
// The stretch value is a (non-negative) percentage; currently we support
|
||||
// values in the range 0 .. 1000. (If the upper limit is ever increased,
|
||||
// the kReverseDistance value used here may need to be adjusted.)
|
||||
// If aTargetStretch is >100, we prefer larger values if available;
|
||||
// if <=100, we prefer smaller values if available.
|
||||
if (aTargetStretch < minStretch) {
|
||||
if (aTargetStretch > mozilla::FontStretch::Normal()) {
|
||||
return minStretch - aTargetStretch;
|
||||
}
|
||||
return (minStretch - aTargetStretch) + kReverseDistance;
|
||||
}
|
||||
if (aTargetStretch > maxStretch) {
|
||||
if (aTargetStretch <= mozilla::FontStretch::Normal()) {
|
||||
return aTargetStretch - maxStretch;
|
||||
}
|
||||
return (aTargetStretch - maxStretch) + kReverseDistance;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Calculate weight distance with values in the range (0..1000). In general,
|
||||
// heavier weights match towards even heavier weights while lighter weights
|
||||
// match towards even lighter weights. Target weight values in the range
|
||||
// [400..500] are special, since they will first match up to 500, then down
|
||||
// towards 0, then up again towards 999.
|
||||
//
|
||||
// Example: with target 600 and font weight 800, distance will be 200. With
|
||||
// target 300 and font weight 600, distance will be 900, since heavier
|
||||
// weights are farther away than lighter weights. If the target is 5 and the
|
||||
// font weight 995, the distance would be 1590 for the same reason.
|
||||
|
||||
// weight distance ==> [0,1600]
|
||||
static inline double WeightDistance(const mozilla::WeightRange& aRange,
|
||||
mozilla::FontWeight aTargetWeight) {
|
||||
const double kNotWithinCentralRange = 100.0;
|
||||
const double kReverseDistance = 600.0;
|
||||
|
||||
mozilla::FontWeight minWeight = aRange.Min();
|
||||
mozilla::FontWeight maxWeight = aRange.Max();
|
||||
|
||||
if (aTargetWeight >= minWeight && aTargetWeight <= maxWeight) {
|
||||
// Target is within the face's range, so it's a perfect match
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (aTargetWeight < mozilla::FontWeight(400)) {
|
||||
// Requested a lighter-than-400 weight
|
||||
if (maxWeight < aTargetWeight) {
|
||||
return aTargetWeight - maxWeight;
|
||||
}
|
||||
// Add reverse-search penalty for bolder faces
|
||||
return (minWeight - aTargetWeight) + kReverseDistance;
|
||||
}
|
||||
|
||||
if (aTargetWeight > mozilla::FontWeight(500)) {
|
||||
// Requested a bolder-than-500 weight
|
||||
if (minWeight > aTargetWeight) {
|
||||
return minWeight - aTargetWeight;
|
||||
}
|
||||
// Add reverse-search penalty for lighter faces
|
||||
return (aTargetWeight - maxWeight) + kReverseDistance;
|
||||
}
|
||||
|
||||
// Special case for requested weight in the [400..500] range
|
||||
if (minWeight > aTargetWeight) {
|
||||
if (minWeight <= mozilla::FontWeight(500)) {
|
||||
// Bolder weight up to 500 is first choice
|
||||
return minWeight - aTargetWeight;
|
||||
}
|
||||
// Other bolder weights get a reverse-search penalty
|
||||
return (minWeight - aTargetWeight) + kReverseDistance;
|
||||
}
|
||||
// Lighter weights are not as good as bolder ones within [400..500]
|
||||
return (aTargetWeight - maxWeight) + kNotWithinCentralRange;
|
||||
}
|
||||
|
||||
#endif /* GFX_FONT_UTILS_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче