mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-23 17:07:31 +09:00
Fix app-unit rounding for border width edges
This commit is contained in:
parent
8f053624dd
commit
cf8b773656
2 changed files with 127 additions and 21 deletions
|
|
@ -319,6 +319,11 @@ nsRuleNode::EnsureInlineDisplay(StyleDisplay& display)
|
|||
}
|
||||
}
|
||||
|
||||
enum class AppUnitRounding {
|
||||
Default,
|
||||
TowardZero
|
||||
};
|
||||
|
||||
static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
||||
nscoord aFontSize,
|
||||
const nsStyleFont* aStyleFont,
|
||||
|
|
@ -326,7 +331,9 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
nsPresContext* aPresContext,
|
||||
bool aUseProvidedRootEmSize,
|
||||
bool aUseUserFontSet,
|
||||
RuleNodeCacheConditions& aConditions);
|
||||
RuleNodeCacheConditions& aConditions,
|
||||
AppUnitRounding aRounding =
|
||||
AppUnitRounding::Default);
|
||||
|
||||
struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
|
||||
public css::NumbersAlreadyNormalizedOps
|
||||
|
|
@ -339,18 +346,21 @@ struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
|
|||
const bool mUseProvidedRootEmSize;
|
||||
const bool mUseUserFontSet;
|
||||
RuleNodeCacheConditions& mConditions;
|
||||
const AppUnitRounding mRounding;
|
||||
|
||||
CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont,
|
||||
nsStyleContext* aStyleContext, nsPresContext* aPresContext,
|
||||
bool aUseProvidedRootEmSize, bool aUseUserFontSet,
|
||||
RuleNodeCacheConditions& aConditions)
|
||||
RuleNodeCacheConditions& aConditions,
|
||||
AppUnitRounding aRounding)
|
||||
: mFontSize(aFontSize),
|
||||
mStyleFont(aStyleFont),
|
||||
mStyleContext(aStyleContext),
|
||||
mPresContext(aPresContext),
|
||||
mUseProvidedRootEmSize(aUseProvidedRootEmSize),
|
||||
mUseUserFontSet(aUseUserFontSet),
|
||||
mConditions(aConditions)
|
||||
mConditions(aConditions),
|
||||
mRounding(aRounding)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -358,15 +368,84 @@ struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
|
|||
{
|
||||
return CalcLengthWith(aValue, mFontSize, mStyleFont,
|
||||
mStyleContext, mPresContext, mUseProvidedRootEmSize,
|
||||
mUseUserFontSet, mConditions);
|
||||
mUseUserFontSet, mConditions, mRounding);
|
||||
}
|
||||
};
|
||||
|
||||
static inline nscoord ScaleCoordRound(const nsCSSValue& aValue, float aFactor)
|
||||
static inline nscoord
|
||||
ScaleCoordWithRounding(const nsCSSValue& aValue, float aFactor,
|
||||
AppUnitRounding aRounding)
|
||||
{
|
||||
if (aRounding == AppUnitRounding::TowardZero) {
|
||||
return NSToCoordTruncClamped(aValue.GetFloatValue() * aFactor);
|
||||
}
|
||||
return NSToCoordRoundWithClamp(aValue.GetFloatValue() * aFactor);
|
||||
}
|
||||
|
||||
static inline nscoord
|
||||
CSSPixelsToAppUnitsWithRounding(float aPixels, AppUnitRounding aRounding)
|
||||
{
|
||||
if (aRounding == AppUnitRounding::TowardZero) {
|
||||
return NSToCoordTruncClamped(double(aPixels) *
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
}
|
||||
return nsPresContext::CSSPixelsToAppUnits(aPixels);
|
||||
}
|
||||
|
||||
static nscoord
|
||||
GetFixedLengthWithRounding(const nsCSSValue& aValue,
|
||||
nsPresContext* aPresContext,
|
||||
AppUnitRounding aRounding)
|
||||
{
|
||||
if (aRounding == AppUnitRounding::Default) {
|
||||
return aValue.GetFixedLength(aPresContext);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_PhysicalMillimeter,
|
||||
"not a fixed length unit");
|
||||
double inches = double(aValue.GetFloatValue()) / MM_PER_INCH_FLOAT;
|
||||
return NSToCoordTruncClamped(
|
||||
inches * aPresContext->DeviceContext()->AppUnitsPerPhysicalInch());
|
||||
}
|
||||
|
||||
static nscoord
|
||||
GetPixelLengthWithRounding(const nsCSSValue& aValue,
|
||||
AppUnitRounding aRounding)
|
||||
{
|
||||
MOZ_ASSERT(aValue.IsPixelLengthUnit(), "not a pixel length unit");
|
||||
|
||||
double scaleFactor;
|
||||
switch (aValue.GetUnit()) {
|
||||
case eCSSUnit_Pixel:
|
||||
return CSSPixelsToAppUnitsWithRounding(aValue.GetFloatValue(),
|
||||
aRounding);
|
||||
case eCSSUnit_Pica:
|
||||
scaleFactor = 16.0;
|
||||
break;
|
||||
case eCSSUnit_Point:
|
||||
scaleFactor = 4.0 / 3.0;
|
||||
break;
|
||||
case eCSSUnit_Inch:
|
||||
scaleFactor = 96.0;
|
||||
break;
|
||||
case eCSSUnit_Millimeter:
|
||||
scaleFactor = 96.0 / 25.4;
|
||||
break;
|
||||
case eCSSUnit_Centimeter:
|
||||
scaleFactor = 96.0 / 2.54;
|
||||
break;
|
||||
case eCSSUnit_Quarter:
|
||||
scaleFactor = 96.0 / 101.6;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("should never get here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CSSPixelsToAppUnitsWithRounding(
|
||||
float(double(aValue.GetFloatValue()) * scaleFactor), aRounding);
|
||||
}
|
||||
|
||||
static inline nscoord ScaleViewportCoordTrunc(const nsCSSValue& aValue,
|
||||
nscoord aViewportSize)
|
||||
{
|
||||
|
|
@ -465,7 +544,8 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
// except when called from
|
||||
// CalcLengthWithInitialFont.
|
||||
bool aUseUserFontSet,
|
||||
RuleNodeCacheConditions& aConditions)
|
||||
RuleNodeCacheConditions& aConditions,
|
||||
AppUnitRounding aRounding)
|
||||
{
|
||||
NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(),
|
||||
"not a length or calc unit");
|
||||
|
|
@ -476,10 +556,10 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
NS_ASSERTION(aPresContext, "Must have prescontext");
|
||||
|
||||
if (aValue.IsFixedLengthUnit()) {
|
||||
return aValue.GetFixedLength(aPresContext);
|
||||
return GetFixedLengthWithRounding(aValue, aPresContext, aRounding);
|
||||
}
|
||||
if (aValue.IsPixelLengthUnit()) {
|
||||
return aValue.GetPixelLength();
|
||||
return GetPixelLengthWithRounding(aValue, aRounding);
|
||||
}
|
||||
if (aValue.IsCalcUnit()) {
|
||||
// For properties for which lengths are the *only* units accepted in
|
||||
|
|
@ -490,7 +570,7 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
CalcLengthCalcOps ops(aFontSize, aStyleFont,
|
||||
aStyleContext, aPresContext,
|
||||
aUseProvidedRootEmSize, aUseUserFontSet,
|
||||
aConditions);
|
||||
aConditions, aRounding);
|
||||
return css::ComputeCalc(aValue, ops);
|
||||
}
|
||||
switch (aValue.GetUnit()) {
|
||||
|
|
@ -623,7 +703,7 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
rootFontSize = rootStyleFont->mFont.size;
|
||||
}
|
||||
|
||||
return ScaleCoordRound(aValue, float(rootFontSize));
|
||||
return ScaleCoordWithRounding(aValue, float(rootFontSize), aRounding);
|
||||
}
|
||||
default:
|
||||
// Fall through to the code for units that can't be stored in the
|
||||
|
|
@ -648,7 +728,7 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
// CSS2.1 specifies that this unit scales to the computed font
|
||||
// size, not the em-width in the font metrics, despite the name.
|
||||
aConditions.SetFontSizeDependency(aFontSize);
|
||||
return ScaleCoordRound(aValue, float(aFontSize));
|
||||
return ScaleCoordWithRounding(aValue, float(aFontSize), aRounding);
|
||||
}
|
||||
case eCSSUnit_XHeight: {
|
||||
aPresContext->SetUsesExChUnits(true);
|
||||
|
|
@ -656,7 +736,7 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
GetMetricsFor(aPresContext, aStyleContext, styleFont,
|
||||
aFontSize, aUseUserFontSet);
|
||||
aConditions.SetUncacheable();
|
||||
return ScaleCoordRound(aValue, float(fm->XHeight()));
|
||||
return ScaleCoordWithRounding(aValue, float(fm->XHeight()), aRounding);
|
||||
}
|
||||
case eCSSUnit_Char: {
|
||||
aPresContext->SetUsesExChUnits(true);
|
||||
|
|
@ -668,8 +748,9 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
|
|||
GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
|
||||
|
||||
aConditions.SetUncacheable();
|
||||
return ScaleCoordRound(aValue, ceil(aPresContext->AppUnitsPerDevPixel() *
|
||||
zeroWidth));
|
||||
return ScaleCoordWithRounding(
|
||||
aValue, ceil(aPresContext->AppUnitsPerDevPixel() * zeroWidth),
|
||||
aRounding);
|
||||
}
|
||||
default:
|
||||
NS_NOTREACHED("unexpected unit");
|
||||
|
|
@ -701,6 +782,20 @@ static inline nscoord CalcLength(const nsCSSValue& aValue,
|
|||
aPresContext, aConditions);
|
||||
}
|
||||
|
||||
static inline nscoord
|
||||
CalcLengthTowardZero(const nsCSSValue& aValue,
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
RuleNodeCacheConditions& aConditions)
|
||||
{
|
||||
NS_ASSERTION(aStyleContext, "Must have style data");
|
||||
|
||||
return CalcLengthWith(aValue, -1, nullptr,
|
||||
aStyleContext, aPresContext,
|
||||
false, true, aConditions,
|
||||
AppUnitRounding::TowardZero);
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
|
||||
const nsCSSValue& aValue)
|
||||
|
|
@ -8048,13 +8143,11 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
|
|||
"Unexpected enum value");
|
||||
border->SetBorderWidth(side,
|
||||
(mPresContext->GetBorderWidthTable())[value.GetIntValue()]);
|
||||
// OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
|
||||
} else if (SetCoord(value, coord, nsStyleCoord(),
|
||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||
aContext, mPresContext, conditions)) {
|
||||
NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
|
||||
} else if (value.IsLengthUnit() || value.IsCalcUnit()) {
|
||||
// clamp negative calc() to 0.
|
||||
border->SetBorderWidth(side, std::max(coord.GetCoordValue(), 0));
|
||||
border->SetBorderWidth(side,
|
||||
std::max(CalcLengthTowardZero(value, aContext, mPresContext,
|
||||
conditions), 0));
|
||||
} else if (eCSSUnit_Inherit == value.GetUnit()) {
|
||||
conditions.SetUncacheable();
|
||||
border->SetBorderWidth(side,
|
||||
|
|
@ -8336,6 +8429,11 @@ nsRuleNode::ComputeOutlineData(void* aStartStruct,
|
|||
eCSSUnit_Revert == outlineWidthValue->GetUnit()) {
|
||||
outline->mOutlineWidth =
|
||||
nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
|
||||
} else if (outlineWidthValue->IsLengthUnit() ||
|
||||
outlineWidthValue->IsCalcUnit()) {
|
||||
outline->mOutlineWidth.SetCoordValue(
|
||||
CalcLengthTowardZero(*outlineWidthValue, aContext, mPresContext,
|
||||
conditions));
|
||||
} else {
|
||||
SetCoord(*outlineWidthValue, outline->mOutlineWidth,
|
||||
parentOutline->mOutlineWidth,
|
||||
|
|
@ -8346,7 +8444,13 @@ nsRuleNode::ComputeOutlineData(void* aStartStruct,
|
|||
// outline-offset: length, inherit
|
||||
nsStyleCoord tempCoord;
|
||||
const nsCSSValue* outlineOffsetValue = aRuleData->ValueForOutlineOffset();
|
||||
if (SetCoord(*outlineOffsetValue, tempCoord,
|
||||
if (outlineOffsetValue->IsLengthUnit() || outlineOffsetValue->IsCalcUnit()) {
|
||||
outline->mOutlineOffset =
|
||||
NS_ROUND_OFFSET_TO_PIXELS(
|
||||
CalcLengthTowardZero(*outlineOffsetValue, aContext, mPresContext,
|
||||
conditions),
|
||||
mPresContext->AppUnitsPerDevPixel());
|
||||
} else if (SetCoord(*outlineOffsetValue, tempCoord,
|
||||
nsStyleCoord(parentOutline->mOutlineOffset,
|
||||
nsStyleCoord::CoordConstructor),
|
||||
SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY |
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ var tests = [
|
|||
["2px", "2px"],
|
||||
["2.75px", "2px"],
|
||||
["2.999px", "2px"],
|
||||
["3px", "3px"],
|
||||
["3.001px", "3px"],
|
||||
];
|
||||
|
||||
function checkWidth(property, setupProperty, setupValue) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue