зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1458301 - Unify font face selection methods to consistently use WeightStyleStretchDistance to evaluate the closeness of an available resource to a requested style. r=jwatt
This commit is contained in:
Родитель
d6b8a750aa
Коммит
a311568f05
|
@ -1524,8 +1524,6 @@ WeightDistance(const gfxFontEntry* aFontEntry, FontWeight aTargetWeight)
|
|||
return distance;
|
||||
}
|
||||
|
||||
#define MAX_DISTANCE 1.0e20 // >> than any WeightStyleStretchDistance result
|
||||
|
||||
static inline double
|
||||
WeightStyleStretchDistance(gfxFontEntry* aFontEntry,
|
||||
const gfxFontStyle& aTargetStyle)
|
||||
|
@ -1625,7 +1623,7 @@ gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
|||
// weight/style/stretch combination, only the last matched font entry will
|
||||
// be added.
|
||||
|
||||
double minDistance = MAX_DISTANCE;
|
||||
double minDistance = INFINITY;
|
||||
gfxFontEntry* matched = nullptr;
|
||||
// iterate in forward order so that faces like 'Bold' are matched before
|
||||
// matching style distance faces such as 'Bold Outline' (see bug 1185812)
|
||||
|
@ -1735,45 +1733,8 @@ void gfxFontFamily::LocalizedName(nsAString& aLocalizedName)
|
|||
aLocalizedName = mName;
|
||||
}
|
||||
|
||||
// metric for how close a given font matches a style
|
||||
static float
|
||||
CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
||||
{
|
||||
float rank = 0;
|
||||
if (aStyle) {
|
||||
// TODO: stretch
|
||||
|
||||
// italics
|
||||
bool wantUpright = aStyle->style.IsNormal();
|
||||
if (aFontEntry->IsUpright() == wantUpright) {
|
||||
rank += 5000.0f;
|
||||
}
|
||||
|
||||
// measure of closeness of weight to the desired value
|
||||
if (aFontEntry->Weight().Min() > aStyle->weight) {
|
||||
rank += 1000.0f - (aFontEntry->Weight().Min() - aStyle->weight);
|
||||
} else if (aFontEntry->Weight().Max() < aStyle->weight) {
|
||||
rank += 1000.0f - (aStyle->weight - aFontEntry->Weight().Max());
|
||||
} else {
|
||||
rank += 2000.0f; // the font supports the exact weight wanted
|
||||
}
|
||||
} else {
|
||||
// if no font to match, prefer non-bold, non-italic fonts
|
||||
if (aFontEntry->IsUpright()) {
|
||||
rank += 2000.0f;
|
||||
}
|
||||
if (aFontEntry->Weight().Min() <= FontWeight(500)) {
|
||||
rank += 1000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
#define RANK_MATCHED_CMAP 10000.0f
|
||||
|
||||
void
|
||||
gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
||||
gfxFontFamily::FindFontForChar(GlobalFontMatch* aMatchData)
|
||||
{
|
||||
if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
|
||||
// none of the faces in the family support the required char,
|
||||
|
@ -1781,81 +1742,72 @@ gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
|||
return;
|
||||
}
|
||||
|
||||
gfxFontEntry *fe =
|
||||
FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle
|
||||
: gfxFontStyle(),
|
||||
true);
|
||||
gfxFontEntry* fe =
|
||||
FindFontForStyle(aMatchData->mStyle, /*aIgnoreSizeTolerance*/ true);
|
||||
if (!fe || fe->SkipDuringSystemFallback()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fe && !fe->SkipDuringSystemFallback()) {
|
||||
float rank = 0;
|
||||
float distance = INFINITY;
|
||||
|
||||
if (fe->HasCharacter(aMatchData->mCh)) {
|
||||
rank += RANK_MATCHED_CMAP;
|
||||
aMatchData->mCount++;
|
||||
if (fe->HasCharacter(aMatchData->mCh)) {
|
||||
aMatchData->mCount++;
|
||||
|
||||
LogModule* log = gfxPlatform::GetLog(eGfxLog_textrun);
|
||||
LogModule* log = gfxPlatform::GetLog(eGfxLog_textrun);
|
||||
|
||||
if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Debug))) {
|
||||
uint32_t unicodeRange = FindCharUnicodeRange(aMatchData->mCh);
|
||||
Script script = GetScriptCode(aMatchData->mCh);
|
||||
MOZ_LOG(log, LogLevel::Debug,\
|
||||
("(textrun-systemfallback-fonts) char: u+%6.6x "
|
||||
"unicode-range: %d script: %d match: [%s]\n",
|
||||
aMatchData->mCh,
|
||||
unicodeRange, int(script),
|
||||
NS_ConvertUTF16toUTF8(fe->Name()).get()));
|
||||
}
|
||||
|
||||
// omitting from original windows code -- family name, lang group, pitch
|
||||
// not available in current FontEntry implementation
|
||||
rank += CalcStyleMatch(fe, aMatchData->mStyle);
|
||||
} else if (!fe->IsNormalStyle()) {
|
||||
// If style/weight/stretch was not Normal, see if we can
|
||||
// fall back to a next-best face (e.g. Arial Black -> Bold,
|
||||
// or Arial Narrow -> Regular).
|
||||
GlobalFontMatch data(aMatchData->mCh, aMatchData->mStyle);
|
||||
SearchAllFontsForChar(&data);
|
||||
if (data.mMatchRank >= RANK_MATCHED_CMAP) {
|
||||
fe = data.mBestMatch;
|
||||
rank = data.mMatchRank;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Debug))) {
|
||||
uint32_t unicodeRange = FindCharUnicodeRange(aMatchData->mCh);
|
||||
Script script = GetScriptCode(aMatchData->mCh);
|
||||
MOZ_LOG(log, LogLevel::Debug,\
|
||||
("(textrun-systemfallback-fonts) char: u+%6.6x "
|
||||
"unicode-range: %d script: %d match: [%s]\n",
|
||||
aMatchData->mCh,
|
||||
unicodeRange, int(script),
|
||||
NS_ConvertUTF16toUTF8(fe->Name()).get()));
|
||||
}
|
||||
|
||||
aMatchData->mCmapsTested++;
|
||||
|
||||
// xxx - add whether AAT font with morphing info for specific lang groups
|
||||
|
||||
if (rank > aMatchData->mMatchRank
|
||||
|| (rank == aMatchData->mMatchRank &&
|
||||
Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0))
|
||||
{
|
||||
aMatchData->mBestMatch = fe;
|
||||
aMatchData->mMatchedFamily = this;
|
||||
aMatchData->mMatchRank = rank;
|
||||
distance = WeightStyleStretchDistance(fe, aMatchData->mStyle);
|
||||
} else if (!fe->IsNormalStyle()) {
|
||||
// If style/weight/stretch was not Normal, see if we can
|
||||
// fall back to a next-best face (e.g. Arial Black -> Bold,
|
||||
// or Arial Narrow -> Regular).
|
||||
GlobalFontMatch data(aMatchData->mCh, aMatchData->mStyle);
|
||||
SearchAllFontsForChar(&data);
|
||||
if (isfinite(data.mMatchDistance)) {
|
||||
fe = data.mBestMatch;
|
||||
distance = data.mMatchDistance;
|
||||
}
|
||||
}
|
||||
aMatchData->mCmapsTested++;
|
||||
|
||||
if (isinf(distance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (distance < aMatchData->mMatchDistance ||
|
||||
(distance == aMatchData->mMatchDistance &&
|
||||
Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0)) {
|
||||
aMatchData->mBestMatch = fe;
|
||||
aMatchData->mMatchedFamily = this;
|
||||
aMatchData->mMatchDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch *aMatchData)
|
||||
gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch* aMatchData)
|
||||
{
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (fe && fe->HasCharacter(aMatchData->mCh)) {
|
||||
float rank = RANK_MATCHED_CMAP;
|
||||
rank += CalcStyleMatch(fe, aMatchData->mStyle);
|
||||
if (rank > aMatchData->mMatchRank
|
||||
|| (rank == aMatchData->mMatchRank &&
|
||||
float distance = WeightStyleStretchDistance(fe, aMatchData->mStyle);
|
||||
if (distance < aMatchData->mMatchDistance
|
||||
|| (distance == aMatchData->mMatchDistance &&
|
||||
Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0))
|
||||
{
|
||||
aMatchData->mBestMatch = fe;
|
||||
aMatchData->mMatchedFamily = this;
|
||||
aMatchData->mMatchRank = rank;
|
||||
aMatchData->mMatchDistance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include <math.h>
|
||||
|
||||
typedef struct gr_face gr_face;
|
||||
|
||||
|
@ -690,20 +691,19 @@ gfxFontEntry::SupportsBold()
|
|||
// used when iterating over all fonts looking for a match for a given character
|
||||
struct GlobalFontMatch {
|
||||
GlobalFontMatch(const uint32_t aCharacter,
|
||||
const gfxFontStyle *aStyle) :
|
||||
mCh(aCharacter), mStyle(aStyle),
|
||||
mMatchRank(0.0f), mCount(0), mCmapsTested(0)
|
||||
const gfxFontStyle& aStyle) :
|
||||
mStyle(aStyle), mCh(aCharacter),
|
||||
mCount(0), mCmapsTested(0), mMatchDistance(INFINITY)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RefPtr<gfxFontEntry> mBestMatch; // current best match
|
||||
RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
|
||||
const gfxFontStyle& mStyle; // style to match
|
||||
const uint32_t mCh; // codepoint to be matched
|
||||
const gfxFontStyle* mStyle; // style to match
|
||||
float mMatchRank; // metric indicating closest match
|
||||
RefPtr<gfxFontEntry> mBestMatch; // current best match
|
||||
RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
|
||||
uint32_t mCount; // number of fonts matched
|
||||
uint32_t mCmapsTested; // number of cmaps tested
|
||||
float mMatchDistance; // metric indicating closest match
|
||||
};
|
||||
|
||||
class gfxFontFamily {
|
||||
|
@ -786,10 +786,10 @@ public:
|
|||
|
||||
// checks for a matching font within the family
|
||||
// used as part of the font fallback process
|
||||
void FindFontForChar(GlobalFontMatch *aMatchData);
|
||||
void FindFontForChar(GlobalFontMatch* aMatchData);
|
||||
|
||||
// checks all fonts for a matching font within the family
|
||||
void SearchAllFontsForChar(GlobalFontMatch *aMatchData);
|
||||
void SearchAllFontsForChar(GlobalFontMatch* aMatchData);
|
||||
|
||||
// read in other family names, if any, and use functor to add each into cache
|
||||
virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
|
||||
|
|
|
@ -682,7 +682,7 @@ gfxPlatformFontList::CommonFontFallback(uint32_t aCh, uint32_t aNextCh,
|
|||
// If style/weight/stretch was not Normal, see if we can
|
||||
// fall back to a next-best face (e.g. Arial Black -> Bold,
|
||||
// or Arial Narrow -> Regular).
|
||||
GlobalFontMatch data(aCh, aMatchStyle);
|
||||
GlobalFontMatch data(aCh, *aMatchStyle);
|
||||
fallback->SearchAllFontsForChar(&data);
|
||||
if (data.mBestMatch) {
|
||||
*aMatchedFamily = fallback;
|
||||
|
@ -715,7 +715,7 @@ gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh,
|
|||
}
|
||||
|
||||
// otherwise, try to find it among local fonts
|
||||
GlobalFontMatch data(aCh, aMatchStyle);
|
||||
GlobalFontMatch data(aCh, *aMatchStyle);
|
||||
|
||||
// iterate over all font families to find a font that support the character
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
|
|
|
@ -2799,7 +2799,7 @@ gfxFontGroup::GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel,
|
|||
gfxFont*
|
||||
gfxFontGroup::FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh)
|
||||
{
|
||||
GlobalFontMatch data(aCh, &mStyle);
|
||||
GlobalFontMatch data(aCh, mStyle);
|
||||
aFamily->SearchAllFontsForChar(&data);
|
||||
gfxFontEntry* fe = data.mBestMatch;
|
||||
if (!fe) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче