Bug 1698495 - Implement size-adjust font scaling in gfx/thebes font code. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D110024
This commit is contained in:
Jonathan Kew 2021-03-29 21:14:44 +00:00
parent 6881212073
commit 39edce2d71
14 changed files with 78 additions and 36 deletions

View File

@ -158,7 +158,7 @@ void gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption) {
(gfxFloat)fontMetrics.xHeight / fontMetrics.designUnitsPerEm;
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
} else {
mAdjustedSize = mStyle.size;
mAdjustedSize = GetAdjustedSize();
}
// Note that GetMeasuringMode depends on mAdjustedSize

View File

@ -223,9 +223,9 @@ void gfxFT2FontBase::InitMetrics() {
// If font-size-adjust is in effect, we need to get metrics in order to
// determine the aspect ratio, then compute the final adjusted size and
// re-initialize metrics.
// This will clamp mFTSize to a minimum of 1.0, and therefore prevent
// further recursion when calling InitMetrics here.
mFTSize = FindClosestSize(mFTFace->GetFace(), GetAdjustedSize());
// Setting mFTSize nonzero here ensures we will not recurse again; the
// actual value will be overridden by FindClosestSize below.
mFTSize = 1.0;
InitMetrics();
// Now do the font-size-adjust calculation and set the final size.
gfxFloat aspect = mMetrics.xHeight / mMetrics.emHeight;
@ -235,6 +235,10 @@ void gfxFT2FontBase::InitMetrics() {
mFTFace->ForgetLockOwner(this);
}
// Set mAdjustedSize if it hasn't already been set by a font-size-adjust
// computation.
mAdjustedSize = GetAdjustedSize();
// Cairo metrics are normalized to em-space, so that whatever fixed size
// might actually be chosen is factored out. They are then later scaled by
// the font matrix to the target adjusted size. Stash the chosen closest

View File

@ -756,7 +756,7 @@ gfxFontconfigFontEntry::UnscaledFontCache::Lookup(const std::string& aFile,
static inline gfxFloat SizeForStyle(gfxFontconfigFontEntry* aEntry,
const gfxFontStyle& aStyle) {
return aStyle.sizeAdjust >= 0.0 ? aStyle.GetAdjustedSize(aEntry->GetAspect())
: aStyle.size;
: aStyle.size * aEntry->mSizeAdjust;
}
static double ChooseFontSize(gfxFontconfigFontEntry* aEntry,

View File

@ -796,7 +796,7 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
: mFontEntry(aFontEntry),
mUnscaledFont(aUnscaledFont),
mStyle(*aFontStyle),
mAdjustedSize(0.0),
mAdjustedSize(-1.0), // negative to indicate "not yet initialized"
mFUnitsConvFactor(-1.0f), // negative to indicate "not yet initialized"
mAntialiasOption(anAAOption),
mIsValid(true),
@ -3664,7 +3664,8 @@ void gfxFont::SanitizeMetrics(gfxFont::Metrics* aMetrics,
// Even if this font size is zero, this font is created with non-zero size.
// However, for layout and others, we should return the metrics of zero size
// font.
if (mStyle.size == 0.0 || mStyle.sizeAdjust == 0.0) {
if (mStyle.size == 0.0 || mStyle.sizeAdjust == 0.0 ||
mFontEntry->mSizeAdjust == 0.0) {
memset(aMetrics, 0, sizeof(gfxFont::Metrics));
return;
}

View File

@ -1490,8 +1490,13 @@ class gfxFont {
}
gfxFloat GetAdjustedSize() const {
return mAdjustedSize > 0.0 ? mAdjustedSize
: (mStyle.sizeAdjust == 0.0 ? 0.0 : mStyle.size);
// mAdjustedSize is cached here if not already set to a non-zero value;
// but it may be overridden by a value computed in metrics initialization
// from font-size-adjust.
if (mAdjustedSize < 0.0) {
mAdjustedSize = mStyle.sizeAdjust == 0.0 ? 0.0 : mStyle.size * mFontEntry->mSizeAdjust;
}
return mAdjustedSize;
}
float FUnitsToDevUnitsFactor() const {
@ -2155,7 +2160,7 @@ class gfxFont {
mozilla::UniquePtr<gfxMathTable> mMathTable;
gfxFontStyle mStyle;
gfxFloat mAdjustedSize;
mutable gfxFloat mAdjustedSize;
// Conversion factor from font units to dev units; note that this may be
// zero (in the degenerate case where mAdjustedSize has become zero).

View File

@ -500,6 +500,9 @@ class gfxFontEntry {
float mDescentOverride = -1.0;
float mLineGapOverride = -1.0;
// Scaling factor to be applied to the font size.
float mSizeAdjust = 1.0;
// For user fonts (only), we need to record whether or not weight/stretch/
// slant variations should be clamped to the range specified in the entry
// properties. When the @font-face rule omitted one or more of these

View File

@ -118,7 +118,7 @@ void gfxGDIFont::Initialize() {
LOGFONTW logFont;
if (mAdjustedSize == 0.0) {
mAdjustedSize = mStyle.size;
mAdjustedSize = GetAdjustedSize();
if (mStyle.sizeAdjust > 0.0 && mAdjustedSize > 0.0) {
// to implement font-size-adjust, we first create the "unadjusted" font
FillLogFont(logFont, mAdjustedSize);

View File

@ -244,7 +244,9 @@ void gfxMacFont::InitMetrics() {
return;
}
mAdjustedSize = std::max(mStyle.size, 1.0);
// Apply any size-adjust from the font enty to the given size; this may be
// re-adjusted below if font-size-adjust is in effect.
mAdjustedSize = std::max(GetAdjustedSize(), 1.0);
mFUnitsConvFactor = mAdjustedSize / upem;
// For CFF fonts, when scaling values read from CGFont* APIs, we need to
@ -275,9 +277,9 @@ void gfxMacFont::InitMetrics() {
mMetrics.capHeight = ::CGFontGetCapHeight(mCGFont) * cgConvFactor;
}
if (mStyle.sizeAdjust > 0.0 && mStyle.size > 0.0 && mMetrics.xHeight > 0.0) {
if (mStyle.sizeAdjust > 0.0 && mMetrics.xHeight > 0.0) {
// apply font-size-adjust, and recalculate metrics
gfxFloat aspect = mMetrics.xHeight / mStyle.size;
gfxFloat aspect = mMetrics.xHeight / mAdjustedSize;
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
mFUnitsConvFactor = mAdjustedSize / upem;
if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {

View File

@ -44,7 +44,8 @@ gfxUserFontEntry::gfxUserFontEntry(
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride)
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust)
: gfxFontEntry("userfont"_ns),
mUserFontLoadState(STATUS_NOT_LOADED),
mFontDataLoadingState(NOT_LOADING),
@ -66,6 +67,7 @@ gfxUserFontEntry::gfxUserFontEntry(
mAscentOverride = aAscentOverride;
mDescentOverride = aDescentOverride;
mLineGapOverride = aLineGapOverride;
mSizeAdjust = aSizeAdjust;
}
void gfxUserFontEntry::UpdateAttributes(
@ -74,7 +76,8 @@ void gfxUserFontEntry::UpdateAttributes(
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride) {
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) {
// Remove the entry from the user font cache, if present there, as the cache
// key may no longer be correct with the new attributes.
gfxUserFontSet::UserFontCache::ForgetFont(this);
@ -91,6 +94,7 @@ void gfxUserFontEntry::UpdateAttributes(
mAscentOverride = aAscentOverride;
mDescentOverride = aDescentOverride;
mLineGapOverride = aLineGapOverride;
mSizeAdjust = aSizeAdjust;
}
gfxUserFontEntry::~gfxUserFontEntry() {
@ -107,7 +111,8 @@ bool gfxUserFontEntry::Matches(
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride) {
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) {
return Weight() == aWeight && Stretch() == aStretch &&
SlantStyle() == aStyle && mFeatureSettings == aFeatureSettings &&
mVariationSettings == aVariationSettings &&
@ -116,6 +121,7 @@ bool gfxUserFontEntry::Matches(
mRangeFlags == aRangeFlags && mAscentOverride == aAscentOverride &&
mDescentOverride == aDescentOverride &&
mLineGapOverride == aLineGapOverride &&
mSizeAdjust == aSizeAdjust &&
((!aUnicodeRanges && !mCharacterMap) ||
(aUnicodeRanges && mCharacterMap &&
mCharacterMap->Equals(aUnicodeRanges)));
@ -437,6 +443,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
fe->mAscentOverride = mAscentOverride;
fe->mDescentOverride = mDescentOverride;
fe->mLineGapOverride = mLineGapOverride;
fe->mSizeAdjust = mSizeAdjust;
// For src:local(), we don't care whether the request is from
// a private window as there's no issue of caching resources;
// local fonts are just available all the time.
@ -734,6 +741,7 @@ bool gfxUserFontEntry::LoadPlatformFont(const uint8_t* aOriginalFontData,
fe->mAscentOverride = mAscentOverride;
fe->mDescentOverride = mDescentOverride;
fe->mLineGapOverride = mLineGapOverride;
fe->mSizeAdjust = mSizeAdjust;
StoreUserFontData(fe, mFontSet->GetPrivateBrowsing(), originalFullName,
&metadata, metaOrigLen, compression);
if (LOG_ENABLED()) {
@ -927,7 +935,8 @@ already_AddRefed<gfxUserFontEntry> gfxUserFontSet::FindOrCreateUserFontEntry(
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride) {
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) {
RefPtr<gfxUserFontEntry> entry;
// If there's already a userfont entry in the family whose descriptors all
@ -941,14 +950,16 @@ already_AddRefed<gfxUserFontEntry> gfxUserFontSet::FindOrCreateUserFontEntry(
entry = FindExistingUserFontEntry(
family, aFontFaceSrcList, aWeight, aStretch, aStyle, aFeatureSettings,
aVariationSettings, aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride);
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride,
aSizeAdjust);
}
if (!entry) {
entry = CreateUserFontEntry(
aFontFaceSrcList, aWeight, aStretch, aStyle, aFeatureSettings,
aVariationSettings, aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride);
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride,
aSizeAdjust);
entry->mFamilyName = aFamilyName;
}
@ -963,7 +974,8 @@ gfxUserFontEntry* gfxUserFontSet::FindExistingUserFontEntry(
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride) {
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) {
nsTArray<RefPtr<gfxFontEntry>>& fontList = aFamily->GetFontList();
for (size_t i = 0, count = fontList.Length(); i < count; i++) {
@ -976,7 +988,8 @@ gfxUserFontEntry* gfxUserFontSet::FindExistingUserFontEntry(
if (!existingUserFontEntry->Matches(
aFontFaceSrcList, aWeight, aStretch, aStyle, aFeatureSettings,
aVariationSettings, aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride)) {
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride,
aSizeAdjust)) {
continue;
}
@ -1135,6 +1148,7 @@ bool gfxUserFontSet::UserFontCache::Entry::KeyEquals(
mFontEntry->mAscentOverride != fe->mAscentOverride ||
mFontEntry->mDescentOverride != fe->mDescentOverride ||
mFontEntry->mLineGapOverride != fe->mLineGapOverride ||
mFontEntry->mSizeAdjust != fe->mSizeAdjust ||
mFontEntry->mFamilyName != fe->mFamilyName) {
return false;
}

View File

@ -267,7 +267,7 @@ class gfxUserFontSet {
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride,
float aLineGapOverride) = 0;
float aLineGapOverride, float aSizeAdjust) = 0;
// creates a font face for the specified family, or returns an existing
// matching entry on the family if there is one
@ -279,7 +279,8 @@ class gfxUserFontSet {
const nsTArray<mozilla::gfx::FontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride);
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust);
// add in a font face for which we have the gfxUserFontEntry already
void AddUserFontEntry(const nsCString& aFamilyName,
@ -529,7 +530,8 @@ class gfxUserFontSet {
const nsTArray<mozilla::gfx::FontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride);
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust);
// creates a new gfxUserFontFamily in mFontFamilies, or returns an existing
// family if there is one
@ -578,7 +580,8 @@ class gfxUserFontEntry : public gfxFontEntry {
const nsTArray<mozilla::gfx::FontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride);
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust);
virtual ~gfxUserFontEntry();
@ -590,7 +593,8 @@ class gfxUserFontEntry : public gfxFontEntry {
const nsTArray<mozilla::gfx::FontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride);
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust);
// Return whether the entry matches the given list of attributes
bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
@ -601,7 +605,7 @@ class gfxUserFontEntry : public gfxFontEntry {
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride,
float aLineGapOverride);
float aLineGapOverride, float aSizeAdjust);
gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override;

View File

@ -52,12 +52,13 @@ class FontFace final : public nsISupports, public nsWrapperCache {
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride)
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust)
: gfxUserFontEntry(aFontSet, aFontFaceSrcList, aWeight, aStretch,
aStyle, aFeatureSettings, aVariationSettings,
aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride,
aLineGapOverride) {}
aLineGapOverride, aSizeAdjust) {}
virtual void SetLoadState(UserFontLoadState aLoadState) override;
virtual void GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult) override;

View File

@ -964,6 +964,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(
float ascentOverride = -1.0;
float descentOverride = -1.0;
float lineGapOverride = -1.0;
float sizeAdjust = 1.0;
gfxFontEntry::RangeFlags rangeFlags = gfxFontEntry::RangeFlags::eNoFlags;
@ -995,6 +996,11 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(
lineGapOverride = lineGap->_0;
}
// set up size-adjust scaling factor
if (Maybe<StylePercentage> percentage = aFontFace->GetSizeAdjust()) {
sizeAdjust = percentage->_0;
}
// set up font features
nsTArray<gfxFontFeature> featureSettings;
aFontFace->GetFontFeatureSettings(featureSettings);
@ -1019,7 +1025,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(
existingEntry->UpdateAttributes(
weight, stretch, italicStyle, featureSettings, variationSettings,
languageOverride, unicodeRanges, fontDisplay, rangeFlags,
ascentOverride, descentOverride, lineGapOverride);
ascentOverride, descentOverride, lineGapOverride, sizeAdjust);
// If the family name has changed, remove the entry from its current family
// and clear the mFamilyName field so it can be reset when added to a new
// family.
@ -1155,7 +1161,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(
RefPtr<gfxUserFontEntry> entry = set->mUserFontSet->FindOrCreateUserFontEntry(
aFamilyName, srcArray, weight, stretch, italicStyle, featureSettings,
variationSettings, languageOverride, unicodeRanges, fontDisplay,
rangeFlags, ascentOverride, descentOverride, lineGapOverride);
rangeFlags, ascentOverride, descentOverride, lineGapOverride, sizeAdjust);
return entry.forget();
}
@ -1827,11 +1833,13 @@ FontFaceSet::UserFontSet::CreateUserFontEntry(
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride) {
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) {
RefPtr<gfxUserFontEntry> entry = new FontFace::Entry(
this, aFontFaceSrcList, aWeight, aStretch, aStyle, aFeatureSettings,
aVariationSettings, aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride);
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride,
aSizeAdjust);
return entry.forget();
}

View File

@ -99,7 +99,7 @@ class FontFaceSet final : public DOMEventTargetHelper,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride,
float aLineGapOverride) override;
float aLineGapOverride, float aSizeAdjust) override;
private:
RefPtr<FontFaceSet> mFontFaceSet;

View File

@ -1,2 +1,2 @@
[size-adjust-text-decoration.tentative.html]
expected: FAIL
prefs: [layout.css.size-adjust.enabled:true]