Bug 1646224 - Use mozilla::Length rather than nscoord to store font sizes. r=heycam,jfkthame

This avoids arbitrary precision loss when computing REM units and so on,
which is particularly important if we ever change the base of our app
units (but useful regardless).

Differential Revision: https://phabricator.services.mozilla.com/D79928
This commit is contained in:
Emilio Cobos Álvarez 2020-06-22 09:45:40 +00:00
parent edecee7890
commit b9b9e38dd9
55 changed files with 286 additions and 327 deletions

View File

@ -426,11 +426,11 @@ TextAttrsMgr::FontSizeTextAttr::FontSizeTextAttr(nsIFrame* aRootFrame,
: TTextAttr<nscoord>(!aFrame) {
mDC = aRootFrame->PresContext()->DeviceContext();
mRootNativeValue = aRootFrame->StyleFont()->mSize;
mRootNativeValue = aRootFrame->StyleFont()->mSize.ToAppUnits();
mIsRootDefined = true;
if (aFrame) {
mNativeValue = aFrame->StyleFont()->mSize;
mNativeValue = aFrame->StyleFont()->mSize.ToAppUnits();
mIsDefined = true;
}
}
@ -441,7 +441,7 @@ bool TextAttrsMgr::FontSizeTextAttr::GetValueFor(Accessible* aAccessible,
if (el) {
nsIFrame* frame = el->GetPrimaryFrame();
if (frame) {
*aValue = frame->StyleFont()->mSize;
*aValue = frame->StyleFont()->mSize.ToAppUnits();
return true;
}
}

View File

@ -75,7 +75,7 @@ test_newtab({
);
const styles = content.getComputedStyle(hr);
is(styles.color, "rgb(255, 0, 0)", "applied and normalized color");
is(styles.fontSize, "46.65px", "applied and normalized font size");
is(styles.fontSize, "46.6583px", "applied and normalized font size");
is(styles.fontWeight, "400", "applied and normalized font weight");
},
});

View File

@ -2359,7 +2359,7 @@ class CanvasUserSpaceMetrics : public UserSpaceMetricsWithSize {
mPresContext(aPresContext) {}
virtual float GetEmLength() const override {
return NSAppUnitsToFloatPixels(mFont.size, AppUnitsPerCSSPixel());
return mFont.size.ToCSSPixels();
}
virtual float GetExLength() const override {
@ -3211,7 +3211,7 @@ bool CanvasRenderingContext2D::SetFontInternal(const nsAString& aFont,
// pixels to CSS pixels, to adjust for the difference in expectations from
// other nsFontMetrics clients.
resizedFont.size =
(fontStyle->mSize * c->AppUnitsPerDevPixel()) / AppUnitsPerCSSPixel();
fontStyle->mSize.ScaledBy(1.0f / c->CSSToDevPixelScale().scale);
c->Document()->FlushUserFontSet();

View File

@ -934,8 +934,8 @@ nsresult ContentEventHandler::GenerateFlatFontRanges(
nsAutoCString name;
fontName.AppendToString(name, false);
AppendUTF8toUTF16(name, fontRange->mFontName);
fontRange->mFontSize =
frame->PresContext()->AppUnitsToDevPixels(font.size);
fontRange->mFontSize = frame->PresContext()->CSSPixelsToDevPixels(
font.size.ToCSSPixels());
}
}
baseOffset += GetBRLength(aLineBreakType);

View File

@ -388,8 +388,7 @@ float SVGContentUtils::GetFontSize(ComputedStyle* aComputedStyle,
MOZ_ASSERT(aComputedStyle);
MOZ_ASSERT(aPresContext);
nscoord fontSize = aComputedStyle->StyleFont()->mSize;
return nsPresContext::AppUnitsToFloatCSSPixels(fontSize) /
return aComputedStyle->StyleFont()->mSize.ToCSSPixels() /
aPresContext->EffectiveTextZoom();
}

View File

@ -8,6 +8,7 @@
#include "gfxFont.h" // for gfxFontStyle
#include "gfxFontFeatures.h" // for gfxFontFeature, etc
#include "gfxFontUtils.h" // for TRUETYPE_TAG
#include "mozilla/ServoStyleConstsInlines.h"
#include "nsCRT.h" // for nsCRT
#include "nsDebug.h" // for NS_ASSERTION
#include "nsISupports.h"
@ -18,10 +19,10 @@
using namespace mozilla;
nsFont::nsFont(const FontFamilyList& aFontlist, nscoord aSize)
nsFont::nsFont(const FontFamilyList& aFontlist, mozilla::Length aSize)
: fontlist(aFontlist), size(aSize) {}
nsFont::nsFont(StyleGenericFontFamily aGenericType, nscoord aSize)
nsFont::nsFont(StyleGenericFontFamily aGenericType, mozilla::Length aSize)
: fontlist(aGenericType), size(aSize) {}
nsFont::nsFont(const nsFont& aOther) = default;
@ -279,10 +280,7 @@ void nsFont::AddFontVariationsToStyle(gfxFontStyle* aStyle) const {
const uint32_t kTagOpsz = TRUETYPE_TAG('o', 'p', 's', 'z');
if (opticalSizing == NS_FONT_OPTICAL_SIZING_AUTO &&
!fontVariationSettings.Contains(kTagOpsz, VariationTagComparator())) {
gfxFontVariation opsz = {
kTagOpsz,
// size is in app units, but we want a floating-point px size
float(size) / float(AppUnitsPerCSSPixel())};
gfxFontVariation opsz = {kTagOpsz, size.ToCSSPixels()};
aStyle->variationSettings.AppendElement(opsz);
}

View File

@ -15,6 +15,7 @@
#include "gfxFontVariations.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/ServoStyleConstsInlines.h"
#include "mozilla/StyleColorInlines.h" // for StyleRGBA
#include "nsCoord.h" // for nscoord
#include "nsTArray.h" // for nsTArray
@ -37,8 +38,8 @@ struct nsFont final {
// Font variations from CSS font-variation-settings
CopyableTArray<gfxFontVariation> fontVariationSettings;
// The logical size of the font, in nscoord units
nscoord size = 0;
// The logical size of the font, in CSS Pixels
mozilla::NonNegativeLength size{0};
// The aspect-value (ie., the ratio actualsize:actualxheight) that any
// actual physical font created from this font structure must have when
@ -94,10 +95,10 @@ struct nsFont final {
bool systemFont = false;
// initialize the font with a fontlist
nsFont(const mozilla::FontFamilyList& aFontlist, nscoord aSize);
nsFont(const mozilla::FontFamilyList& aFontlist, mozilla::Length aSize);
// initialize the font with a single generic
nsFont(mozilla::StyleGenericFontFamily, nscoord aSize);
nsFont(mozilla::StyleGenericFontFamily, mozilla::Length aSize);
// Make a copy of the given font
nsFont(const nsFont& aFont);

View File

@ -117,12 +117,13 @@ nsFontMetrics::nsFontMetrics(const nsFont& aFont, const Params& aParams,
mTextRunRTL(false),
mVertical(false),
mTextOrientation(mozilla::StyleTextOrientation::Mixed) {
gfxFontStyle style(
aFont.style, aFont.weight, aFont.stretch, gfxFloat(aFont.size) / mP2A,
aParams.language, aParams.explicitLanguage, aFont.sizeAdjust,
aFont.systemFont, mDeviceContext->IsPrinterContext(),
aFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
aFont.synthesis & NS_FONT_SYNTHESIS_STYLE, aFont.languageOverride);
gfxFontStyle style(aFont.style, aFont.weight, aFont.stretch,
gfxFloat(aFont.size.ToAppUnits()) / mP2A, aParams.language,
aParams.explicitLanguage, aFont.sizeAdjust,
aFont.systemFont, mDeviceContext->IsPrinterContext(),
aFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
aFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
aFont.languageOverride);
aFont.AddFontFeaturesToStyle(&style, mOrientation == eVertical);
style.featureValueLookup = aParams.featureValueLookup;

View File

@ -10557,8 +10557,7 @@ void ReflowCountMgr::PaintCount(const char* aName,
// We don't care about the document language or user fonts here;
// just get a default Latin font.
nsFont font(StyleGenericFontFamily::Serif,
nsPresContext::CSSPixelsToAppUnits(11));
nsFont font(StyleGenericFontFamily::Serif, Length::FromPixels(11));
nsFontMetrics::Params params;
params.language = nsGkAtoms::x_western;
params.textPerf = aPresContext->GetTextPerfMetrics();

View File

@ -92,8 +92,8 @@ void LangGroupFontPrefs::Initialize(nsStaticAtom* aLangGroupAtom) {
nsAutoCString langGroup;
aLangGroupAtom->ToUTF8String(langGroup);
mDefaultVariableFont.size = nsPresContext::CSSPixelsToAppUnits(16);
mDefaultMonospaceFont.size = nsPresContext::CSSPixelsToAppUnits(13);
mDefaultVariableFont.size = Length::FromPixels(16.0f);
mDefaultMonospaceFont.size = Length::FromPixels(13.0f);
nsAutoCString pref;
@ -102,7 +102,7 @@ void LangGroupFontPrefs::Initialize(nsStaticAtom* aLangGroupAtom) {
MAKE_FONT_PREF_KEY(pref, "font.minimum-size.", langGroup);
int32_t size = Preferences::GetInt(pref.get());
mMinimumFontSize = nsPresContext::CSSPixelsToAppUnits(size);
mMinimumFontSize = Length::FromPixels(size);
// clang-format off
nsFont* fontTypes[] = {
@ -186,7 +186,7 @@ void LangGroupFontPrefs::Initialize(nsStaticAtom* aLangGroupAtom) {
MAKE_FONT_PREF_KEY(pref, "font.size", generic_dot_langGroup);
size = Preferences::GetInt(pref.get());
if (size > 0) {
font->size = nsPresContext::CSSPixelsToAppUnits(size);
font->size = Length::FromPixels(size);
}
// get font.size-adjust.[generic].[langGroup]

View File

@ -20,13 +20,13 @@ struct LangGroupFontPrefs {
// Font sizes default to zero; they will be set in GetFontPreferences
LangGroupFontPrefs()
: mLangGroup(nullptr),
mMinimumFontSize(0),
mMinimumFontSize({0}),
mDefaultVariableFont(),
mDefaultSerifFont(StyleGenericFontFamily::Serif, 0),
mDefaultSansSerifFont(StyleGenericFontFamily::SansSerif, 0),
mDefaultMonospaceFont(StyleGenericFontFamily::Monospace, 0),
mDefaultCursiveFont(StyleGenericFontFamily::Cursive, 0),
mDefaultFantasyFont(StyleGenericFontFamily::Fantasy, 0) {
mDefaultSerifFont(StyleGenericFontFamily::Serif, {0}),
mDefaultSansSerifFont(StyleGenericFontFamily::SansSerif, {0}),
mDefaultMonospaceFont(StyleGenericFontFamily::Monospace, {0}),
mDefaultCursiveFont(StyleGenericFontFamily::Cursive, {0}),
mDefaultFantasyFont(StyleGenericFontFamily::Fantasy, {0}) {
mDefaultVariableFont.fontlist.SetDefaultFontType(
StyleGenericFontFamily::Serif);
// We create mDefaultVariableFont.fontlist with defaultType as the
@ -80,7 +80,7 @@ struct LangGroupFontPrefs {
}
nsStaticAtom* mLangGroup;
nscoord mMinimumFontSize;
Length mMinimumFontSize;
nsFont mDefaultVariableFont;
nsFont mDefaultSerifFont;
nsFont mDefaultSansSerifFont;

View File

@ -249,7 +249,6 @@ typedef gfx::Matrix4x4Typed<ParentLayerPixel, RenderTargetPixel>
*/
struct CSSPixel {
// Conversions from app units
static CSSCoord FromAppUnits(nscoord aCoord) {
return NSAppUnitsToFloatPixels(aCoord, float(AppUnitsPerCSSPixel()));
}
@ -356,6 +355,12 @@ struct CSSPixel {
NSToCoordRoundWithClamp(float(aRect.Height()) *
float(AppUnitsPerCSSPixel())));
}
// Conversion from a given CSS point value.
static CSSCoord FromPoints(float aCoord) {
// One inch / 72.
return aCoord * 96.0f / 72.0f;
}
};
/*

View File

@ -4877,7 +4877,7 @@ already_AddRefed<nsFontMetrics> nsLayoutUtils::GetFontMetricsForComputedStyle(
}
nsFont font = styleFont->mFont;
font.size = NSToCoordRound(font.size * aInflation);
font.size.ScaleBy(aInflation);
font.variantWidth = aVariantWidth;
return aPresContext->DeviceContext()->GetMetricsFor(font, params);
}
@ -7506,7 +7506,8 @@ nsIFrame* nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) {
result |= gfx::ShapedTextFlags::TEXT_OPTIMIZE_SPEED;
break;
case StyleTextRendering::Auto:
if (aStyleFont->mFont.size < aPresContext->GetAutoQualityMinFontSize()) {
if (aStyleFont->mFont.size.ToCSSPixels() <
aPresContext->GetAutoQualityMinFontSize()) {
result |= gfx::ShapedTextFlags::TEXT_OPTIMIZE_SPEED;
}
break;
@ -8390,7 +8391,7 @@ float nsLayoutUtils::FontSizeInflationInner(const nsIFrame* aFrame,
// Note that line heights should be inflated by the same ratio as the
// font size of the same text; thus we operate only on the font size
// even when we're scaling a line height.
nscoord styleFontSize = aFrame->StyleFont()->mFont.size;
nscoord styleFontSize = aFrame->StyleFont()->mFont.size.ToAppUnits();
if (styleFontSize <= 0) {
// Never scale zero font size.
return 1.0;
@ -10188,7 +10189,7 @@ nsLayoutUtils::ControlCharVisibilityDefault() {
/* static */
already_AddRefed<nsFontMetrics> nsLayoutUtils::GetMetricsFor(
nsPresContext* aPresContext, bool aIsVertical,
const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet) {
const nsStyleFont* aStyleFont, Length aFontSize, bool aUseUserFontSet) {
nsFont font = aStyleFont->mFont;
font.size = aFontSize;
gfxFont::Orientation orientation =
@ -10221,7 +10222,7 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
aSystemFont->systemFont = fontStyle.systemFont;
aSystemFont->weight = fontStyle.weight;
aSystemFont->stretch = fontStyle.stretch;
aSystemFont->size = CSSPixel::ToAppUnits(fontStyle.size);
aSystemFont->size = Length::FromPixels(fontStyle.size);
// aSystemFont->langGroup = fontStyle.langGroup;
aSystemFont->sizeAdjust = fontStyle.sizeAdjust;
@ -10245,9 +10246,8 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
// always use 2 points smaller than what the browser has defined as
// the default proportional font.
// Assumption: system defined font is proportional
aSystemFont->size = std::max(
aDefaultVariableFont->size - nsPresContext::CSSPointsToAppUnits(2),
0);
aSystemFont->size = Length::FromPixels(
std::max(aDefaultVariableFont->size.ToCSSPixels() - 2.0f, 0.0f));
}
#endif
}

View File

@ -3045,7 +3045,8 @@ class nsLayoutUtils {
// aUseUserFontSet is true.
static already_AddRefed<nsFontMetrics> GetMetricsFor(
nsPresContext* aPresContext, bool aIsVertical,
const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet);
const nsStyleFont* aStyleFont, mozilla::Length aFontSize,
bool aUseUserFontSet);
static void ComputeSystemFont(nsFont* aSystemFont,
mozilla::LookAndFeel::FontID aFontID,

View File

@ -551,8 +551,8 @@ class nsPresContext : public nsISupports,
}
void SetOverridePrefersColorScheme(const Maybe<StylePrefersColorScheme>&);
nscoord GetAutoQualityMinFontSize() {
return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
mozilla::CSSCoord GetAutoQualityMinFontSize() const {
return DevPixelsToFloatCSSPixels(mAutoQualityMinFontSizePixelsPref);
}
/**

View File

@ -194,7 +194,8 @@ LogicalSize nsMeterFrame::ComputeAutoSize(
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);
autoSize.BSize(wm) = autoSize.ISize(wm) = fontMet->Font().size; // 1em
autoSize.BSize(wm) = autoSize.ISize(wm) =
fontMet->Font().size.ToAppUnits(); // 1em
if (ResolvedOrientationIsVertical() == wm.IsVertical()) {
autoSize.ISize(wm) *= 5; // 5em
@ -209,7 +210,7 @@ nscoord nsMeterFrame::GetMinISize(gfxContext* aRenderingContext) {
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
nscoord minISize = fontMet->Font().size; // 1em
nscoord minISize = fontMet->Font().size.ToAppUnits(); // 1em
if (ResolvedOrientationIsVertical() == GetWritingMode().IsVertical()) {
// The orientation is inline

View File

@ -209,8 +209,9 @@ LogicalSize nsProgressFrame::ComputeAutoSize(
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);
autoSize.BSize(wm) = autoSize.ISize(wm) =
NSToCoordRound(StyleFont()->mFont.size *
nsLayoutUtils::FontSizeInflationFor(this)); // 1em
StyleFont()
->mFont.size.ScaledBy(nsLayoutUtils::FontSizeInflationFor(this))
.ToAppUnits(); // 1em
if (ResolvedOrientationIsVertical() == wm.IsVertical()) {
autoSize.ISize(wm) *= 10; // 10em
@ -225,7 +226,7 @@ nscoord nsProgressFrame::GetMinISize(gfxContext* aRenderingContext) {
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
nscoord minISize = fontMet->Font().size; // 1em
nscoord minISize = fontMet->Font().size.ToAppUnits(); // 1em
if (ResolvedOrientationIsVertical() == GetWritingMode().IsVertical()) {
// The orientation is inline

View File

@ -613,7 +613,7 @@ nsresult nsRangeFrame::AttributeChanged(int32_t aNameSpaceID,
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
}
nscoord nsRangeFrame::AutoCrossSize(nscoord aEm) {
nscoord nsRangeFrame::AutoCrossSize(Length aEm) {
nscoord minCrossSize(0);
if (IsThemed()) {
bool unused;
@ -624,7 +624,12 @@ nscoord nsRangeFrame::AutoCrossSize(nscoord aEm) {
minCrossSize =
pc->DevPixelsToAppUnits(IsHorizontal() ? size.height : size.width);
}
return std::max(minCrossSize, NSToCoordRound(CROSS_AXIS_EM_SIZE * aEm));
return std::max(minCrossSize, aEm.ScaledBy(CROSS_AXIS_EM_SIZE).ToAppUnits());
}
static mozilla::Length OneEm(nsRangeFrame* aFrame) {
return aFrame->StyleFont()->mFont.size.ScaledBy(
nsLayoutUtils::FontSizeInflationFor(aFrame));
}
LogicalSize nsRangeFrame::ComputeAutoSize(
@ -633,16 +638,16 @@ LogicalSize nsRangeFrame::ComputeAutoSize(
const LogicalSize& aBorder, const LogicalSize& aPadding,
ComputeSizeFlags aFlags) {
bool isInlineOriented = IsInlineOriented();
auto em = StyleFont()->mFont.size * nsLayoutUtils::FontSizeInflationFor(this);
auto em = OneEm(this);
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);
if (isInlineOriented) {
autoSize.ISize(wm) = NSToCoordRound(MAIN_AXIS_EM_SIZE * em);
autoSize.ISize(wm) = em.ScaledBy(MAIN_AXIS_EM_SIZE).ToAppUnits();
autoSize.BSize(wm) = AutoCrossSize(em);
} else {
autoSize.ISize(wm) = AutoCrossSize(em);
autoSize.BSize(wm) = NSToCoordRound(MAIN_AXIS_EM_SIZE * em);
autoSize.BSize(wm) = em.ScaledBy(MAIN_AXIS_EM_SIZE).ToAppUnits();
}
return autoSize.ConvertTo(aWM, wm);
@ -661,9 +666,11 @@ nscoord nsRangeFrame::GetMinISize(gfxContext* aRenderingContext) {
}
nscoord nsRangeFrame::GetPrefISize(gfxContext* aRenderingContext) {
bool isInline = IsInlineOriented();
auto em = StyleFont()->mFont.size * nsLayoutUtils::FontSizeInflationFor(this);
return isInline ? NSToCoordRound(em * MAIN_AXIS_EM_SIZE) : AutoCrossSize(em);
auto em = OneEm(this);
if (IsInlineOriented()) {
return em.ScaledBy(MAIN_AXIS_EM_SIZE).ToAppUnits();
}
return AutoCrossSize(em);
}
bool nsRangeFrame::IsHorizontal() const {

View File

@ -141,7 +141,7 @@ class nsRangeFrame final : public nsContainerFrame,
private:
// Return our preferred size in the cross-axis (the axis perpendicular
// to the direction of movement of the thumb).
nscoord AutoCrossSize(nscoord aEm);
nscoord AutoCrossSize(mozilla::Length aEm);
nsresult MakeAnonymousDiv(Element** aResult, PseudoStyleType aPseudoType,
nsTArray<ContentInfo>& aElements);

View File

@ -20,7 +20,7 @@ nscoord ColumnUtils::GetColumnGap(const nsContainerFrame* aFrame,
nscoord aPercentageBasis) {
const auto& columnGap = aFrame->StylePosition()->mColumnGap;
if (columnGap.IsNormal()) {
return aFrame->StyleFont()->mFont.size;
return aFrame->StyleFont()->mFont.size.ToAppUnits();
}
return nsLayoutUtils::ResolveGapToLength(columnGap, aPercentageBasis);
}

View File

@ -632,7 +632,7 @@ void MathMLTextRunFactory::RebuildTextRun(
// Get the correct gfxFontGroup that corresponds to the earlier font changes.
if (length) {
font.size = NSToCoordRound(font.size * mFontInflation);
font.size = font.size.ScaledBy(mFontInflation);
nsPresContext* pc = styles[0]->mPresContext;
nsFontMetrics::Params params;
params.language = styles[0]->mLanguage;

View File

@ -2732,8 +2732,9 @@ static inline nscoord ComputeLineHeight(ComputedStyle* aComputedStyle,
// For factor units the computed value of the line-height property
// is found by multiplying the factor by the font's computed size
// (adjusted for min-size prefs and text zoom).
return NSToCoordRound(lineHeight.number._0 * aFontSizeInflation *
aComputedStyle->StyleFont()->mFont.size);
return aComputedStyle->StyleFont()
->mFont.size.ScaledBy(lineHeight.AsNumber() * aFontSizeInflation)
.ToAppUnits();
}
MOZ_ASSERT(lineHeight.IsNormal() || lineHeight.IsMozBlockHeight());

View File

@ -335,7 +335,7 @@ void nsFontInflationData::ScanTextIn(nsIFrame* aFrame) {
ComputeApproximateLengthWithWhitespaceCompression(
content->AsText(), kid->StyleText());
if (len != 0) {
nscoord fontSize = kid->StyleFont()->mFont.size;
nscoord fontSize = kid->StyleFont()->mFont.size.ToAppUnits();
if (fontSize > 0) {
mTextAmount += fontSize * len;
}
@ -344,20 +344,20 @@ void nsFontInflationData::ScanTextIn(nsIFrame* aFrame) {
} else if (fType == LayoutFrameType::TextInput) {
// We don't want changes to the amount of text in a text input
// to change what we count towards inflation.
nscoord fontSize = kid->StyleFont()->mFont.size;
nscoord fontSize = kid->StyleFont()->mFont.size.ToAppUnits();
int32_t charCount = static_cast<nsTextControlFrame*>(kid)->GetCols();
mTextAmount += charCount * fontSize;
} else if (fType == LayoutFrameType::ComboboxControl) {
// See textInputFrame above (with s/amount of text/selected option/).
// Don't just recurse down to the list control inside, since we
// need to exclude the display frame.
nscoord fontSize = kid->StyleFont()->mFont.size;
nscoord fontSize = kid->StyleFont()->mFont.size.ToAppUnits();
int32_t charCount = CharCountOfLargestOption(
static_cast<nsComboboxControlFrame*>(kid)->GetDropDown());
mTextAmount += charCount * fontSize;
} else if (fType == LayoutFrameType::ListControl) {
// See textInputFrame above (with s/amount of text/selected option/).
nscoord fontSize = kid->StyleFont()->mFont.size;
nscoord fontSize = kid->StyleFont()->mFont.size.ToAppUnits();
int32_t charCount = CharCountOfLargestOption(kid);
mTextAmount += charCount * fontSize;
} else {

View File

@ -63,7 +63,8 @@ nsPageSequenceFrame::nsPageSequenceFrame(ComputedStyle* aStyle,
->Document()
->GetFontPrefsForLang(aStyle->StyleFont()->mLanguage)
->GetDefaultFont(StyleGenericFontFamily::Serif);
mPageData->mHeadFootFont.size = nsPresContext::CSSPointsToAppUnits(10);
mPageData->mHeadFootFont.size =
Length::FromPixels(CSSPixel::FromPoints(10.0f));
// Doing this here so we only have to go get these formats once
SetPageNumberFormat("pagenumber", "%1$d", true);

View File

@ -5626,13 +5626,14 @@ gfxFloat nsTextFrame::ComputeSelectionUnderlineHeight(
// the default font size, we should use the actual font size because the
// computed value from the default font size can be too thick for the
// current font size.
nscoord defaultFontSize =
Length defaultFontSize =
aPresContext->Document()
->GetFontPrefsForLang(nullptr)
->GetDefaultFont(StyleGenericFontFamily::None)
->size;
int32_t zoomedFontSize = aPresContext->AppUnitsToDevPixels(
nsStyleFont::ZoomText(*aPresContext->Document(), defaultFontSize));
int32_t zoomedFontSize = aPresContext->CSSPixelsToDevPixels(
nsStyleFont::ZoomText(*aPresContext->Document(), defaultFontSize)
.ToCSSPixels());
gfxFloat fontSize =
std::min(gfxFloat(zoomedFontSize), aFontMetrics.emHeight);
fontSize = std::max(fontSize, 1.0);

View File

@ -64,7 +64,7 @@ static void NormalizeDefaultFont(nsFont& aFont, float aFontSizeInflation) {
aFont.fontlist.SetFontlist(std::move(names));
aFont.fontlist.SetDefaultFontType(StyleGenericFontFamily::None);
}
aFont.size = NSToCoordRound(aFont.size * aFontSizeInflation);
aFont.size.ScaleBy(aFontSizeInflation);
}
// -----------------------------------------------------------------------------

View File

@ -1099,7 +1099,7 @@ static nscoord GetInterFrameSpacing(int32_t aScriptLevel,
}
static nscoord GetThinSpace(const nsStyleFont* aStyleFont) {
return NSToCoordRound(float(aStyleFont->mFont.size) * float(3) / float(18));
return aStyleFont->mFont.size.ScaledBy(3.0f / 18.0f).ToAppUnits();
}
class nsMathMLContainerFrame::RowChildFrameIterator {

View File

@ -211,8 +211,10 @@ nscoord nsMathMLFrame::CalcLength(nsPresContext* aPresContext,
if (eCSSUnit_EM == unit) {
const nsStyleFont* font = aComputedStyle->StyleFont();
return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size);
} else if (eCSSUnit_XHeight == unit) {
return font->mFont.size.ScaledBy(aCSSValue.GetFloatValue()).ToAppUnits();
}
if (eCSSUnit_XHeight == unit) {
aPresContext->SetUsesExChUnits(true);
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForComputedStyle(
aComputedStyle, aPresContext, aFontSizeInflation);

View File

@ -238,7 +238,7 @@ class nsMathMLFrame : public nsIMathMLFrame {
// should switch to this API in order to scale with changes of TextZoom
emHeight = fm->EmHeight();
#else
emHeight = NSToCoordRound(float(fm->Font().size));
emHeight = fm->Font().size.ToAppUnits();
#endif
}

View File

@ -1341,22 +1341,22 @@ void Gecko_nsStyleFont_PrioritizeUserFonts(
}
}
nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont* aFont,
const Document* aDocument) {
Length Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont* aFont,
const Document* aDocument) {
// Don't change font-size:0, since that would un-hide hidden text,
// or SVG text, or chrome docs, we assume those know what they do.
if (aFont->mSize == 0 || !aFont->mAllowZoomAndMinSize ||
if (aFont->mSize.IsZero() || !aFont->mAllowZoomAndMinSize ||
nsContentUtils::IsChromeDoc(aDocument)) {
return 0;
return {0};
}
nscoord minFontSize;
Length minFontSize;
bool needsCache = false;
auto MinFontSize = [&](bool* aNeedsToCache) {
auto* prefs =
aDocument->GetFontPrefsForLang(aFont->mLanguage, aNeedsToCache);
return prefs ? prefs->mMinimumFontSize : 0;
return prefs ? prefs->mMinimumFontSize : Length{0};
};
{
@ -1369,30 +1369,23 @@ nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont* aFont,
minFontSize = MinFontSize(nullptr);
}
if (minFontSize < 0) {
return 0;
if (minFontSize.ToCSSPixels() <= 0.0f) {
return {0};
}
return (minFontSize * aFont->mMinFontSizeRatio) / 100;
minFontSize.ScaleBy(aFont->mMinFontSizeRatio);
minFontSize.ScaleBy(1.0f / 100.0f);
return minFontSize;
}
void FontSizePrefs::CopyFrom(const LangGroupFontPrefs& prefs) {
mDefaultVariableSize = prefs.mDefaultVariableFont.size;
mDefaultSerifSize = prefs.mDefaultSerifFont.size;
mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size;
mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size;
mDefaultCursiveSize = prefs.mDefaultCursiveFont.size;
mDefaultFantasySize = prefs.mDefaultFantasyFont.size;
}
FontSizePrefs Gecko_GetBaseSize(nsAtom* aLanguage) {
StyleDefaultFontSizes Gecko_GetBaseSize(nsAtom* aLanguage) {
LangGroupFontPrefs prefs;
nsStaticAtom* langGroupAtom =
StaticPresData::Get()->GetUncachedLangGroup(aLanguage);
prefs.Initialize(langGroupAtom);
FontSizePrefs sizes;
sizes.CopyFrom(prefs);
return sizes;
return {prefs.mDefaultVariableFont.size, prefs.mDefaultSerifFont.size,
prefs.mDefaultSansSerifFont.size, prefs.mDefaultMonospaceFont.size,
prefs.mDefaultCursiveFont.size, prefs.mDefaultFantasyFont.size};
}
static StaticRefPtr<UACacheReporter> gUACacheReporter;
@ -1431,9 +1424,8 @@ void AssertIsMainThreadOrServoFontMetricsLocked() {
GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext* aPresContext,
bool aIsVertical,
const nsStyleFont* aFont,
nscoord aFontSize, bool aUseUserFontSet) {
Length aFontSize, bool aUseUserFontSet) {
AutoWriteLock guard(*sServoFFILock);
GeckoFontMetrics ret;
// Getting font metrics can require some main thread only work to be
// done, such as work that needs to touch non-threadsafe refcounted
@ -1448,18 +1440,19 @@ GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext* aPresContext,
nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
presContext->SetUsesExChUnits(true);
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetMetricsFor(
presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet);
const auto& metrics =
fm->GetThebesFontGroup()->GetFirstValidFont()->GetMetrics(
fm->Orientation());
ret.mXSize = fm->XHeight();
gfxFloat zeroWidth = fm->GetThebesFontGroup()
->GetFirstValidFont()
->GetMetrics(fm->Orientation())
.zeroWidth;
ret.mChSize = zeroWidth >= 0.0
? NS_round(aPresContext->AppUnitsPerDevPixel() * zeroWidth)
: -1.0;
return ret;
int32_t d2a = aPresContext->AppUnitsPerDevPixel();
auto ToLength = [](nscoord aLen) {
return Length::FromPixels(CSSPixel::FromAppUnits(aLen));
};
return {ToLength(NS_round(metrics.xHeight * d2a)),
ToLength(NS_round(metrics.zeroWidth * d2a))};
}
NS_IMPL_THREADSAFE_FFI_REFCOUNTING(SheetLoadDataHolder, SheetLoadDataHolder);

View File

@ -501,24 +501,24 @@ void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont,
void Gecko_nsStyleFont_PrioritizeUserFonts(
nsStyleFont* font, mozilla::StyleGenericFontFamily aDefaultGeneric);
nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont*,
const mozilla::dom::Document*);
mozilla::Length Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont*,
const mozilla::dom::Document*);
// Computes the default generic font for a generic family and language.
mozilla::StyleGenericFontFamily Gecko_nsStyleFont_ComputeDefaultFontType(
const mozilla::dom::Document*,
mozilla::StyleGenericFontFamily generic_family, nsAtom* language);
mozilla::FontSizePrefs Gecko_GetBaseSize(nsAtom* lang);
mozilla::StyleDefaultFontSizes Gecko_GetBaseSize(nsAtom* lang);
struct GeckoFontMetrics {
nscoord mChSize; // -1.0 indicates not found
nscoord mXSize;
mozilla::Length mXSize;
mozilla::Length mChSize; // negatives indicate not found.
};
GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext*, bool is_vertical,
const nsStyleFont* font,
nscoord font_size,
mozilla::Length font_size,
bool use_user_font_set);
mozilla::StyleSheet* Gecko_StyleSheet_Clone(

View File

@ -576,6 +576,7 @@ cbindgen-types = [
{ gecko = "StyleSVGOpacity", servo = "crate::values::computed::svg::SVGOpacity" },
{ gecko = "StyleSVGLength", servo = "crate::values::computed::svg::SVGLength" },
{ gecko = "StyleFontSizeKeyword", servo = "crate::values::specified::font::FontSizeKeyword" },
{ gecko = "StyleDefaultFontSizes", servo = "crate::gecko::wrapper::DefaultFontSizes" },
]
mapped-generic-types = [

View File

@ -487,6 +487,10 @@ bool StyleCSSPixelLength::IsZero() const { return _0 == 0.0f; }
void StyleCSSPixelLength::ScaleBy(float aScale) { _0 *= aScale; }
StyleCSSPixelLength StyleCSSPixelLength::ScaledBy(float aScale) const {
return FromPixels(ToCSSPixels() * aScale);
}
nscoord StyleCSSPixelLength::ToAppUnits() const {
// We want to resolve the length part of the calc() expression rounding 0.5
// away from zero, instead of the default behavior of

View File

@ -150,16 +150,6 @@ struct MediumFeaturesChangedResult {
bool mUsesViewportUnits;
};
struct FontSizePrefs {
void CopyFrom(const mozilla::LangGroupFontPrefs&);
nscoord mDefaultVariableSize;
nscoord mDefaultSerifSize;
nscoord mDefaultSansSerifSize;
nscoord mDefaultMonospaceSize;
nscoord mDefaultCursiveSize;
nscoord mDefaultFantasySize;
};
} // namespace mozilla
#endif // mozilla_ServoTypes_h

View File

@ -2181,7 +2181,7 @@ bool nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord) {
fCoord /= presContext->EffectiveTextZoom();
}
if (font->mFont.size != font->mSize) {
fCoord = fCoord * (float(font->mSize) / float(font->mFont.size));
fCoord *= font->mSize.ToCSSPixels() / font->mFont.size.ToCSSPixels();
}
aCoord = NSToCoordRound(fCoord);

View File

@ -244,7 +244,7 @@ nsStyleFont::nsStyleFont(const Document& aDocument)
StyleGenericFontFamily::None)),
mSize(ZoomText(aDocument, mFont.size)),
mFontSizeFactor(1.0),
mFontSizeOffset(0),
mFontSizeOffset{0},
mFontSizeKeyword(StyleFontSizeKeyword::Medium),
mGenericID(StyleGenericFontFamily::None),
mScriptLevel(0),
@ -254,17 +254,18 @@ nsStyleFont::nsStyleFont(const Document& aDocument)
mExplicitLanguage(false),
mAllowZoomAndMinSize(true),
mScriptUnconstrainedSize(mSize),
mScriptMinSize(nsPresContext::CSSTwipsToAppUnits(
NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT))),
mScriptMinSize(Length::FromPixels(
CSSPixel::FromPoints(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT))),
mScriptSizeMultiplier(NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER),
mLanguage(aDocument.GetLanguageForStyle()) {
MOZ_COUNT_CTOR(nsStyleFont);
MOZ_ASSERT(NS_IsMainThread());
mFont.size = mSize;
if (!nsContentUtils::IsChromeDoc(&aDocument)) {
nscoord minimumFontSize =
Length minimumFontSize =
aDocument.GetFontPrefsForLang(mLanguage)->mMinimumFontSize;
mFont.size = std::max(mSize, minimumFontSize);
mFont.size = Length::FromPixels(
std::max(mSize.ToCSSPixels(), minimumFontSize.ToCSSPixels()));
}
}
@ -303,14 +304,11 @@ nsChangeHint nsStyleFont::CalcDifference(const nsStyleFont& aNewData) const {
return nsChangeHint(0);
}
nscoord nsStyleFont::ZoomText(const Document& aDocument, nscoord aSize) {
float textZoom = 1.0;
Length nsStyleFont::ZoomText(const Document& aDocument, Length aSize) {
if (auto* pc = aDocument.GetPresContext()) {
textZoom = pc->EffectiveTextZoom();
aSize.ScaleBy(pc->EffectiveTextZoom());
}
// aSize can be negative (e.g.: calc(-1px)) so we can't assert that here.
// The caller is expected deal with that.
return NSToCoordTruncClamped(float(aSize) * textZoom);
return aSize;
}
template <typename T>

View File

@ -14,6 +14,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/ServoStyleConstsInlines.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/StyleColorInlines.h"
#include "mozilla/UniquePtr.h"
@ -84,24 +85,27 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont {
nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
/**
* Return aSize multiplied by the current text zoom factor (in aPresContext).
* aSize is allowed to be negative, but the caller is expected to deal with
* negative results. The result is clamped to nscoord_MIN .. nscoord_MAX.
* Return a given size multiplied by the current text zoom factor (in
* aPresContext).
*
* The size is allowed to be negative, but the caller is expected to deal with
* negative results.
*/
static nscoord ZoomText(const mozilla::dom::Document&, nscoord aSize);
static mozilla::Length ZoomText(const mozilla::dom::Document&,
mozilla::Length);
nsFont mFont;
nscoord mSize; // Our "computed size". Can be different
// from mFont.size which is our "actual size" and is
// enforced to be >= the user's preferred min-size.
// mFont.size should be used for display purposes
// while mSize is the value to return in
// getComputedStyle() for example.
// Our "computed size". Can be different from mFont.size which is our "actual
// size" and is enforced to be >= the user's preferred min-size. mFont.size
// should be used for display purposes while mSize is the value to return in
// getComputedStyle() for example.
mozilla::NonNegativeLength mSize;
// In stylo these three track whether the size is keyword-derived
// and if so if it has been modified by a factor/offset
float mFontSizeFactor;
nscoord mFontSizeOffset;
mozilla::Length mFontSizeOffset;
mozilla::StyleFontSizeKeyword mFontSizeKeyword;
mozilla::StyleGenericFontFamily mGenericID;
@ -125,8 +129,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont {
bool mAllowZoomAndMinSize;
// The value mSize would have had if scriptminsize had never been applied
nscoord mScriptUnconstrainedSize;
nscoord mScriptMinSize; // length
mozilla::NonNegativeLength mScriptUnconstrainedSize;
mozilla::Length mScriptMinSize;
float mScriptSizeMultiplier;
RefPtr<nsAtom> mLanguage;
};

View File

@ -141,7 +141,6 @@ support-files = bug517224.sjs
[test_bug635286.html]
[test_bug652486.html]
[test_bug657143.html]
[test_bug664955.html]
[test_bug667520.html]
[test_bug645998.html]
support-files = file_bug645998-1.css file_bug645998-2.css

View File

@ -1,37 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=664955
-->
<head>
<title>Test for Bug 664955</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=664955">Mozilla Bug 664955</a>
<p id="display" style="font-size: 10000000000px"> <!-- must be superior to nscoord_MAX * 60 -->
<span id="larger" style="font-size: larger">
<span id="larger-again" style="font-size: larger">
</span>
</span>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 664955 **/
var parentSize = document.defaultView.getComputedStyle($('display')).fontSize;
var largerSize = document.defaultView.getComputedStyle($('larger')).fontSize;
var largerAgainSize = document.defaultView.getComputedStyle($('larger-again')).fontSize;
is(parentSize, largerSize, "font size is larger than max font size");
is(parentSize, largerAgainSize, "font size is larger than max font size");
</script>
</pre>
</body>
</html>

View File

@ -5140,7 +5140,9 @@ bool SVGTextFrame::UpdateFontSizeScaleFactor() {
nsPresContext* presContext = PresContext();
bool geometricPrecision = false;
nscoord min = nscoord_MAX, max = nscoord_MIN;
CSSCoord min = std::numeric_limits<float>::max();
CSSCoord max = std::numeric_limits<float>::min();
bool anyText = false;
// Find the minimum and maximum font sizes used over all the
// nsTextFrames.
@ -5153,25 +5155,24 @@ bool SVGTextFrame::UpdateFontSizeScaleFactor() {
geometricPrecision = f->StyleText()->mTextRendering ==
StyleTextRendering::Geometricprecision;
}
nscoord size = f->StyleFont()->mFont.size;
if (size) {
min = std::min(min, size);
max = std::max(max, size);
const auto& fontSize = f->StyleFont()->mFont.size;
if (!fontSize.IsZero()) {
min = std::min(min, fontSize.ToCSSPixels());
max = std::max(max, fontSize.ToCSSPixels());
anyText = true;
}
f = it.Next();
}
if (min == nscoord_MAX) {
if (!anyText) {
// No text, so no need for scaling.
mFontSizeScaleFactor = 1.0;
return mFontSizeScaleFactor != oldFontSizeScaleFactor;
}
double minSize = nsPresContext::AppUnitsToFloatCSSPixels(min);
if (geometricPrecision) {
// We want to ensure minSize is scaled to PRECISE_SIZE.
mFontSizeScaleFactor = PRECISE_SIZE / minSize;
mFontSizeScaleFactor = PRECISE_SIZE / min;
return mFontSizeScaleFactor != oldFontSizeScaleFactor;
}
@ -5189,8 +5190,6 @@ bool SVGTextFrame::UpdateFontSizeScaleFactor() {
}
mLastContextScale = contextScale;
double maxSize = nsPresContext::AppUnitsToFloatCSSPixels(max);
// But we want to ignore any scaling required due to HiDPI displays, since
// regular CSS text frames will still create text runs using the font size
// in CSS pixels, and we want SVG text to have the same rendering as HTML
@ -5199,14 +5198,14 @@ bool SVGTextFrame::UpdateFontSizeScaleFactor() {
presContext->AppUnitsPerDevPixel());
contextScale *= cssPxPerDevPx;
double minTextRunSize = minSize * contextScale;
double maxTextRunSize = maxSize * contextScale;
double minTextRunSize = min * contextScale;
double maxTextRunSize = max * contextScale;
if (minTextRunSize >= CLAMP_MIN_SIZE && maxTextRunSize <= CLAMP_MAX_SIZE) {
// We are already in the ideal font size range for all text frames,
// so we only have to take into account the contextScale.
mFontSizeScaleFactor = contextScale;
} else if (maxSize / minSize > CLAMP_MAX_SIZE / CLAMP_MIN_SIZE) {
} else if (max / min > CLAMP_MAX_SIZE / CLAMP_MIN_SIZE) {
// We can't scale the font sizes so that all of the text frames lie
// within our ideal font size range.
// Heuristically, if the maxTextRunSize is within the CLAMP_MAX_SIZE
@ -5214,18 +5213,18 @@ bool SVGTextFrame::UpdateFontSizeScaleFactor() {
// get a valid font for the maxTextRunSize one, we should honor it.
// The same for minTextRunSize.
if (maxTextRunSize <= CLAMP_MAX_SIZE) {
mFontSizeScaleFactor = CLAMP_MAX_SIZE / maxSize;
mFontSizeScaleFactor = CLAMP_MAX_SIZE / max;
} else if (minTextRunSize >= CLAMP_MIN_SIZE) {
mFontSizeScaleFactor = CLAMP_MIN_SIZE / minSize;
mFontSizeScaleFactor = CLAMP_MIN_SIZE / min;
} else {
// So maxTextRunSize is too big, minTextRunSize is too small,
// we can't really do anything for this case, just leave it as is.
mFontSizeScaleFactor = contextScale;
}
} else if (minTextRunSize < CLAMP_MIN_SIZE) {
mFontSizeScaleFactor = CLAMP_MIN_SIZE / minSize;
mFontSizeScaleFactor = CLAMP_MIN_SIZE / min;
} else {
mFontSizeScaleFactor = CLAMP_MAX_SIZE / maxSize;
mFontSizeScaleFactor = CLAMP_MAX_SIZE / max;
}
return mFontSizeScaleFactor != oldFontSizeScaleFactor;

View File

@ -11,6 +11,7 @@ use crate::gecko_bindings::structs;
use crate::media_queries::MediaType;
use crate::properties::ComputedValues;
use crate::string_cache::Atom;
use crate::values::computed::Length;
use crate::values::specified::font::FONT_MEDIUM_PX;
use crate::values::{CustomIdent, KeyframesName};
use app_units::{Au, AU_PER_PX};
@ -19,7 +20,7 @@ use euclid::default::Size2D;
use euclid::{Scale, SideOffsets2D};
use servo_arc::Arc;
use std::fmt;
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
use style_traits::viewport::ViewportConstraints;
use style_traits::{CSSPixel, DevicePixel};
@ -30,15 +31,16 @@ pub struct Device {
/// `Device`, so having a raw document pointer here is fine.
document: *const structs::Document,
default_values: Arc<ComputedValues>,
/// The font size of the root element
/// This is set when computing the style of the root
/// element, and used for rem units in other elements.
/// The font size of the root element.
///
/// When computing the style of the root element, there can't be any
/// other style being computed at the same time, given we need the style of
/// the parent to compute everything else. So it is correct to just use
/// a relaxed atomic here.
root_font_size: AtomicIsize,
/// This is set when computing the style of the root element, and used for
/// rem units in other elements.
///
/// When computing the style of the root element, there can't be any other
/// style being computed at the same time, given we need the style of the
/// parent to compute everything else. So it is correct to just use a
/// relaxed atomic here.
root_font_size: AtomicU32,
/// The body text color, stored as an `nscolor`, used for the "tables
/// inherit from body" quirk.
///
@ -85,8 +87,7 @@ impl Device {
Device {
document,
default_values: ComputedValues::default_values(doc),
// FIXME(bz): Seems dubious?
root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX as i32).0 as isize),
root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize),
used_root_font_size: AtomicBool::new(false),
used_viewport_size: AtomicBool::new(false),
@ -131,15 +132,15 @@ impl Device {
}
/// Get the font size of the root element (for rem)
pub fn root_font_size(&self) -> Au {
pub fn root_font_size(&self) -> Length {
self.used_root_font_size.store(true, Ordering::Relaxed);
Au::new(self.root_font_size.load(Ordering::Relaxed) as i32)
Length::new(f32::from_bits(self.root_font_size.load(Ordering::Relaxed)))
}
/// Set the font size of the root element (for rem)
pub fn set_root_font_size(&self, size: Au) {
pub fn set_root_font_size(&self, size: Length) {
self.root_font_size
.store(size.0 as isize, Ordering::Relaxed)
.store(size.px().to_bits(), Ordering::Relaxed)
}
/// Sets the body text color for the "inherit color from body" quirk.
@ -298,13 +299,13 @@ impl Device {
/// Applies text zoom to a font-size or line-height value (see nsStyleFont::ZoomText).
#[inline]
pub fn zoom_text(&self, size: Au) -> Au {
pub fn zoom_text(&self, size: Length) -> Length {
size.scale_by(self.effective_text_zoom())
}
/// Un-apply text zoom.
#[inline]
pub fn unzoom_text(&self, size: Au) -> Au {
pub fn unzoom_text(&self, size: Length) -> Length {
size.scale_by(1. / self.effective_text_zoom())
}

View File

@ -71,7 +71,6 @@ use crate::values::computed::font::GenericFontFamily;
use crate::values::computed::Length;
use crate::values::specified::length::FontBaseSize;
use crate::CaseSensitivityExt;
use app_units::Au;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator};
use selectors::attr::{CaseSensitivity, NamespaceConstraint};
@ -922,14 +921,12 @@ fn get_animation_rule(
#[derive(Debug)]
/// Gecko font metrics provider
pub struct GeckoFontMetricsProvider {
/// Cache of base font sizes for each language
/// Cache of base font sizes for each language. Usually will have 1 element.
///
/// Usually will have 1 element.
///
// This may be slow on pages using more languages, might be worth optimizing
// by caching lang->group mapping separately and/or using a hashmap on larger
// loads.
pub font_size_cache: RefCell<Vec<(Atom, crate::gecko_bindings::structs::FontSizePrefs)>>,
/// This may be slow on pages using more languages, might be worth
/// optimizing by caching lang->group mapping separately and/or using a
/// hashmap on larger loads.
pub font_size_cache: RefCell<Vec<(Atom, DefaultFontSizes)>>,
}
impl GeckoFontMetricsProvider {
@ -952,8 +949,9 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
return sizes.1.size_for_generic(font_family);
}
let sizes = unsafe { bindings::Gecko_GetBaseSize(font_name.as_ptr()) };
let size = sizes.size_for_generic(font_family);
cache.push((font_name.clone(), sizes));
sizes.size_for_generic(font_family)
size
}
fn query(
@ -967,7 +965,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
None => return Default::default(),
};
let size = Au::from(base_size.resolve(context));
let size = base_size.resolve(context);
let style = context.style();
let (wm, font) = match base_size {
@ -987,15 +985,15 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
pc,
vertical_metrics,
font.gecko(),
size.0,
size,
// we don't use the user font set in a media query
!context.in_media_query,
)
};
FontMetrics {
x_height: Some(Au(gecko_metrics.mXSize).into()),
zero_advance_measure: if gecko_metrics.mChSize >= 0 {
Some(Au(gecko_metrics.mChSize).into())
x_height: Some(gecko_metrics.mXSize),
zero_advance_measure: if gecko_metrics.mChSize.px() >= 0. {
Some(gecko_metrics.mChSize)
} else {
None
},
@ -1003,20 +1001,31 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
}
}
impl structs::FontSizePrefs {
/// The default font sizes for generic families for a given language group.
#[derive(Debug)]
#[repr(C)]
pub struct DefaultFontSizes {
variable: Length,
serif: Length,
sans_serif: Length,
monospace: Length,
cursive: Length,
fantasy: Length,
}
impl DefaultFontSizes {
fn size_for_generic(&self, font_family: GenericFontFamily) -> Length {
Au(match font_family {
GenericFontFamily::None => self.mDefaultVariableSize,
GenericFontFamily::Serif => self.mDefaultSerifSize,
GenericFontFamily::SansSerif => self.mDefaultSansSerifSize,
GenericFontFamily::Monospace => self.mDefaultMonospaceSize,
GenericFontFamily::Cursive => self.mDefaultCursiveSize,
GenericFontFamily::Fantasy => self.mDefaultFantasySize,
match font_family {
GenericFontFamily::None => self.variable,
GenericFontFamily::Serif => self.serif,
GenericFontFamily::SansSerif => self.sans_serif,
GenericFontFamily::Monospace => self.monospace,
GenericFontFamily::Cursive => self.cursive,
GenericFontFamily::Fantasy => self.fantasy,
GenericFontFamily::MozEmoji => unreachable!(
"Should never get here, since this doesn't (yet) appear on font family"
),
})
.into()
}
}
}

View File

@ -845,7 +845,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
fn recompute_keyword_font_size_if_needed(&mut self) {
use crate::values::computed::ToComputedValue;
use crate::values::specified;
use app_units::Au;
if !self.seen.contains(LonghandId::XLang) &&
!self.seen.contains(LonghandId::FontFamily) {
@ -863,7 +862,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
}
};
if font.gecko().mScriptUnconstrainedSize == Au::from(new_size.size()).0 {
if font.gecko().mScriptUnconstrainedSize == new_size.size {
return;
}
@ -878,6 +877,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
#[cfg(feature = "gecko")]
fn constrain_font_size_if_needed(&mut self) {
use crate::gecko_bindings::bindings;
use crate::values::generics::NonNegative;
if !self.seen.contains(LonghandId::XLang) &&
!self.seen.contains(LonghandId::FontFamily) &&
@ -896,11 +896,11 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
)
};
if font.mFont.size >= min_font_size {
if font.mFont.size.0 >= min_font_size {
return;
}
min_font_size
NonNegative(min_font_size)
};
builder.mutate_font().gecko_mut().mFont.size = min_font_size;
@ -942,8 +942,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
/// not clear to me. For now just pretend those don't exist here.
#[cfg(feature = "gecko")]
fn handle_mathml_scriptlevel_if_needed(&mut self) {
use app_units::Au;
use std::cmp;
use crate::values::generics::NonNegative;
if !self.seen.contains(LonghandId::MozScriptLevel) &&
!self.seen.contains(LonghandId::MozScriptMinSize) &&
@ -968,14 +967,14 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
return;
}
let mut min = Au(parent_font.mScriptMinSize);
let mut min = parent_font.mScriptMinSize;
if font.mAllowZoomAndMinSize {
min = builder.device.zoom_text(min);
}
let scale = (parent_font.mScriptSizeMultiplier as f32).powi(delta as i32);
let parent_size = Au(parent_font.mSize);
let parent_unconstrained_size = Au(parent_font.mScriptUnconstrainedSize);
let parent_size = parent_font.mSize.0;
let parent_unconstrained_size = parent_font.mScriptUnconstrainedSize.0;
let new_size = parent_size.scale_by(scale);
let new_unconstrained_size = parent_unconstrained_size.scale_by(scale);
@ -987,7 +986,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
if parent_size <= min {
(parent_size, new_unconstrained_size)
} else {
(cmp::max(min, new_size), new_unconstrained_size)
(min.max(new_size), new_unconstrained_size)
}
} else {
// If the new unconstrained size is larger than the min size,
@ -996,15 +995,15 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
// However, if the new size is even larger (perhaps due to usage
// of em units), use that instead.
(
cmp::min(new_size, cmp::max(new_unconstrained_size, min)),
new_size.min(new_unconstrained_size.max(min)),
new_unconstrained_size
)
}
};
let font = builder.mutate_font().gecko_mut();
font.mFont.size = new_size.0;
font.mSize = new_size.0;
font.mScriptUnconstrainedSize = new_unconstrained_size.0;
font.mFont.size = NonNegative(new_size);
font.mSize = NonNegative(new_size);
font.mScriptUnconstrainedSize = NonNegative(new_unconstrained_size);
}
/// Various properties affect how font-size and font-family are computed.

View File

@ -376,18 +376,6 @@ def set_gecko_property(ffi_name, expr):
<%call expr="impl_simple_clone(ident, gecko_ffi_name)"></%call>
</%def>
<%def name="impl_absolute_length(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
${set_gecko_property(gecko_ffi_name, "v.to_i32_au()")}
}
<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
Au(self.gecko.${gecko_ffi_name}).into()
}
</%def>
<%def name="impl_non_negative_length(ident, gecko_ffi_name, inherit_from=None,
round_to_pixels=False)">
#[allow(non_snake_case)]
@ -593,11 +581,6 @@ impl Clone for ${style_struct.gecko_struct_name} {
longhands = [x for x in style_struct.longhands
if not (skip_longhands == "*" or x.name in skip_longhands.split())]
# Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = {
"MozScriptMinSize": impl_absolute_length,
}
def longhand_method(longhand):
args = dict(ident=longhand.ident, gecko_ffi_name=longhand.gecko_ffi_name)
@ -610,8 +593,6 @@ impl Clone for ${style_struct.gecko_struct_name} {
args.update(keyword=longhand.keyword)
if "font" in longhand.ident:
args.update(cast_type=longhand.cast_type)
elif longhand.predefined_type in predefined_types:
method = predefined_types[longhand.predefined_type]
else:
method = impl_simple
@ -920,9 +901,10 @@ fn static_assert() {
}
pub fn unzoom_fonts(&mut self, device: &Device) {
self.gecko.mSize = device.unzoom_text(Au(self.gecko.mSize)).0;
self.gecko.mScriptUnconstrainedSize = device.unzoom_text(Au(self.gecko.mScriptUnconstrainedSize)).0;
self.gecko.mFont.size = device.unzoom_text(Au(self.gecko.mFont.size)).0;
use crate::values::generics::NonNegative;
self.gecko.mSize = NonNegative(device.unzoom_text(self.gecko.mSize.0));
self.gecko.mScriptUnconstrainedSize = NonNegative(device.unzoom_text(self.gecko.mScriptUnconstrainedSize.0));
self.gecko.mFont.size = NonNegative(device.unzoom_text(self.gecko.mFont.size.0));
}
pub fn copy_font_size_from(&mut self, other: &Self) {
@ -942,25 +924,27 @@ fn static_assert() {
}
pub fn set_font_size(&mut self, v: FontSize) {
let size = Au::from(v.size());
self.gecko.mScriptUnconstrainedSize = size.0;
let size = v.size;
self.gecko.mScriptUnconstrainedSize = size;
// These two may be changed from Cascade::fixup_font_stuff.
self.gecko.mSize = size.0;
self.gecko.mFont.size = size.0;
self.gecko.mSize = size;
self.gecko.mFont.size = size;
self.gecko.mFontSizeKeyword = v.keyword_info.kw;
self.gecko.mFontSizeFactor = v.keyword_info.factor;
self.gecko.mFontSizeOffset = v.keyword_info.offset.to_i32_au();
self.gecko.mFontSizeOffset = v.keyword_info.offset;
}
pub fn clone_font_size(&self) -> FontSize {
use crate::values::specified::font::KeywordInfo;
FontSize {
size: Au(self.gecko.mSize).into(),
size: self.gecko.mSize,
keyword_info: KeywordInfo {
kw: self.gecko.mFontSizeKeyword,
factor: self.gecko.mFontSizeFactor,
offset: Au(self.gecko.mFontSizeOffset).into()
offset: self.gecko.mFontSizeOffset,
}
}
}

View File

@ -307,7 +307,6 @@ ${helpers.predefined_type(
//! variable reference. We may want to improve this behavior at some
//! point. See also https://github.com/w3c/csswg-drafts/issues/1586.
use app_units::Au;
use cssparser::{Parser, ToCss};
use crate::values::computed::font::GenericFontFamily;
use crate::properties::longhands;
@ -397,7 +396,7 @@ ${helpers.predefined_type(
is_system_font: true,
},
font_size: FontSize {
size: NonNegative(cx.maybe_zoom_text(Au(system.size).into())),
size: NonNegative(cx.maybe_zoom_text(system.size.0)),
keyword_info: KeywordInfo::none()
},
font_weight,

View File

@ -17,7 +17,7 @@ use app_units::Au;
use cssparser::RGBA;
use euclid::default::Size2D as UntypedSize2D;
use euclid::{Scale, SideOffsets2D, Size2D};
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use style_traits::viewport::ViewportConstraints;
use style_traits::{CSSPixel, DevicePixel};
@ -43,7 +43,7 @@ pub struct Device {
/// the parent to compute everything else. So it is correct to just use
/// a relaxed atomic here.
#[ignore_malloc_size_of = "Pure stack type"]
root_font_size: AtomicIsize,
root_font_size: AtomicU32,
/// Whether any styles computed in the document relied on the root font-size
/// by using rem units.
#[ignore_malloc_size_of = "Pure stack type"]
@ -68,7 +68,7 @@ impl Device {
viewport_size,
device_pixel_ratio,
// FIXME(bz): Seems dubious?
root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX).0 as isize),
root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
used_root_font_size: AtomicBool::new(false),
used_viewport_units: AtomicBool::new(false),
environment: CssEnvironment,
@ -90,15 +90,15 @@ impl Device {
}
/// Get the font size of the root element (for rem)
pub fn root_font_size(&self) -> Au {
pub fn root_font_size(&self) -> CSSPixelLength {
self.used_root_font_size.store(true, Ordering::Relaxed);
Au::new(self.root_font_size.load(Ordering::Relaxed) as i32)
CSSPixelLength::new(f32::from_bits(self.root_font_size.load(Ordering::Relaxed)))
}
/// Set the font size of the root element (for rem)
pub fn set_root_font_size(&self, size: Au) {
pub fn set_root_font_size(&self, size: CSSPixelLength) {
self.root_font_size
.store(size.0 as isize, Ordering::Relaxed)
.store(size.px().to_bits(), Ordering::Relaxed)
}
/// Sets the body text color for the "inherit color from body" quirk.

View File

@ -12,7 +12,6 @@ use crate::properties::longhands::float::computed_value::T as Float;
use crate::properties::longhands::overflow_x::computed_value::T as Overflow;
use crate::properties::longhands::position::computed_value::T as Position;
use crate::properties::{self, ComputedValues, StyleBuilder};
use app_units::Au;
/// A struct that implements all the adjustment methods.
///
@ -414,7 +413,9 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
.none_or_hidden() &&
self.style.get_outline().outline_has_nonzero_width()
{
self.style.mutate_outline().set_outline_width(Au(0).into());
self.style
.mutate_outline()
.set_outline_width(crate::Zero::zero());
}
}

View File

@ -156,7 +156,7 @@ impl FontSize {
/// Get default value of font size.
pub fn medium() -> Self {
Self {
size: NonNegative(Length::new(specified::FONT_MEDIUM_PX as CSSFloat)),
size: NonNegative(Length::new(specified::FONT_MEDIUM_PX)),
keyword_info: KeywordInfo::medium(),
}
}

View File

@ -224,6 +224,12 @@ impl CSSPixelLength {
CSSPixelLength(px)
}
/// Scale the length by a given amount.
#[inline]
pub fn scale_by(self, scale: CSSFloat) -> Self {
CSSPixelLength(self.0 * scale)
}
/// Return the containing pixel value.
#[inline]
pub fn px(self) -> CSSFloat {

View File

@ -231,7 +231,7 @@ impl<'a> Context<'a> {
// -x-text-zoom property, which leads to a false value
// in mAllowZoomAndMinSize
if self.style().get_font().gecko.mAllowZoomAndMinSize {
self.device().zoom_text(Au::from(size)).into()
self.device().zoom_text(size)
} else {
size
}

View File

@ -779,13 +779,13 @@ impl ToComputedValue for FontSizeAdjust {
const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
/// The default font size.
pub const FONT_MEDIUM_PX: i32 = 16;
pub const FONT_MEDIUM_PX: f32 = 16.0;
impl FontSizeKeyword {
#[inline]
#[cfg(feature = "servo")]
fn to_length(&self, _: &Context) -> NonNegativeLength {
let medium = Length::new(FONT_MEDIUM_PX as f32);
let medium = Length::new(FONT_MEDIUM_PX);
// https://drafts.csswg.org/css-fonts-3/#font-size-prop
NonNegative(match *self {
FontSizeKeyword::XXSmall => medium * 3.0 / 5.0,

View File

@ -241,7 +241,7 @@ impl FontRelativeLength {
let reference_size = if context.builder.is_root_element || context.in_media_query {
reference_font_size
} else {
computed::Length::new(context.device().root_font_size().to_f32_px())
context.device().root_font_size()
};
(reference_size, length)
},

View File

@ -219,6 +219,7 @@ include = [
"TextAlignLast",
"FontSizeKeyword",
"AspectRatio",
"DefaultFontSizes",
]
item_types = ["enums", "structs", "unions", "typedefs", "functions", "constants"]
renaming_overrides_prefixing = true
@ -277,10 +278,14 @@ renaming_overrides_prefixing = true
[export.body]
"CSSPixelLength" = """
static StyleCSSPixelLength FromPixels(CSSCoord aCoord) { return {aCoord}; }
static StyleCSSPixelLength Zero() { return FromPixels(0.0f); }
inline nscoord ToAppUnits() const;
inline bool IsZero() const;
CSSCoord ToCSSPixels() const { return _0; }
inline void ScaleBy(float);
inline StyleCSSPixelLength ScaledBy(float) const;
"""
"GenericCalcNode" = """

View File

@ -1,13 +0,0 @@
[line-height-interpolation.html]
[CSS Transitions: property <line-height> from [4q\] to [14q\] at (1.5) should be [19q\]]
expected: FAIL
[CSS Animations: property <line-height> from [4q\] to [14q\] at (1.5) should be [19q\]]
expected: FAIL
[CSS Transitions with transition: all: property <line-height> from [4q\] to [14q\] at (1.5) should be [19q\]]
expected: FAIL
[Web Animations: property <line-height> from [4q\] to [14q\] at (1.5) should be [19q\]]
expected: FAIL

View File

@ -1682,8 +1682,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
return fieldFontStyle.size;
}();
const gfxFloat fontSize =
CSSPixel::FromAppUnits(aFrame->StyleFont()->mFont.size);
const gfxFloat fontSize = aFrame->StyleFont()->mFont.size.ToCSSPixels();
if (fieldFontSizeInCSSPixels > fontSize) {
contentHeight =
std::round(contentHeight * fontSize / fieldFontSizeInCSSPixels);