зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1287054 part 2 - support vw, vh, vmin and vmax units for non-CSS lengths r=emilio,jgilbert
Differential Revision: https://phabricator.services.mozilla.com/D180619
This commit is contained in:
Родитель
2c9fa6fab2
Коммит
7b6c56870c
|
@ -2820,6 +2820,10 @@ class CanvasUserSpaceMetrics : public UserSpaceMetricsWithSize {
|
|||
}
|
||||
gfx::Size GetSize() const override { return Size(mSize); }
|
||||
|
||||
CSSSize GetCSSViewportSize() const override {
|
||||
return GetCSSViewportSizeFromContext(mPresContext);
|
||||
}
|
||||
|
||||
private:
|
||||
GeckoFontMetrics GetFontMetricsForType(Type aType) const override {
|
||||
switch (aType) {
|
||||
|
|
|
@ -178,6 +178,11 @@ float UserSpaceMetrics::GetCapHeight(Type aType) const {
|
|||
return GetEmLength(aType);
|
||||
}
|
||||
|
||||
CSSSize UserSpaceMetrics::GetCSSViewportSizeFromContext(
|
||||
const nsPresContext* aContext) {
|
||||
return CSSPixel::FromAppUnits(aContext->GetSizeForViewportUnits());
|
||||
}
|
||||
|
||||
SVGElementMetrics::SVGElementMetrics(const SVGElement* aSVGElement,
|
||||
const SVGViewportElement* aCtx)
|
||||
: mSVGElement(aSVGElement), mCtx(aCtx) {}
|
||||
|
@ -210,6 +215,17 @@ float SVGElementMetrics::GetAxisLength(uint8_t aCtxType) const {
|
|||
return FixAxisLength(mCtx->GetLength(aCtxType));
|
||||
}
|
||||
|
||||
CSSSize SVGElementMetrics::GetCSSViewportSize() const {
|
||||
if (!mSVGElement) {
|
||||
return {0.0f, 0.0f};
|
||||
}
|
||||
nsPresContext* context = nsContentUtils::GetContextForContent(mSVGElement);
|
||||
if (!context) {
|
||||
return {0.0f, 0.0f};
|
||||
}
|
||||
return GetCSSViewportSizeFromContext(context);
|
||||
}
|
||||
|
||||
bool SVGElementMetrics::EnsureCtx() const {
|
||||
if (!mCtx && mSVGElement) {
|
||||
mCtx = mSVGElement->GetCtx();
|
||||
|
@ -279,6 +295,10 @@ gfx::Size NonSVGFrameUserSpaceMetrics::GetSize() const {
|
|||
return SVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(mFrame);
|
||||
}
|
||||
|
||||
CSSSize NonSVGFrameUserSpaceMetrics::GetCSSViewportSize() const {
|
||||
return GetCSSViewportSizeFromContext(mFrame->PresContext());
|
||||
}
|
||||
|
||||
float UserSpaceMetricsWithSize::GetAxisLength(uint8_t aCtxType) const {
|
||||
gfx::Size size = GetSize();
|
||||
float length;
|
||||
|
|
|
@ -42,6 +42,7 @@ class UserSpaceMetrics {
|
|||
static GeckoFontMetrics DefaultFontMetrics();
|
||||
static GeckoFontMetrics GetFontMetrics(const Element* aElement);
|
||||
static WritingMode GetWritingMode(const Element* aElement);
|
||||
static CSSSize GetCSSViewportSizeFromContext(const nsPresContext* aContext);
|
||||
|
||||
virtual ~UserSpaceMetrics() = default;
|
||||
|
||||
|
@ -51,6 +52,7 @@ class UserSpaceMetrics {
|
|||
float GetIcWidth(Type aType) const;
|
||||
float GetCapHeight(Type aType) const;
|
||||
virtual float GetAxisLength(uint8_t aCtxType) const = 0;
|
||||
virtual CSSSize GetCSSViewportSize() const = 0;
|
||||
|
||||
protected:
|
||||
virtual GeckoFontMetrics GetFontMetricsForType(Type aType) const = 0;
|
||||
|
@ -72,6 +74,7 @@ class SVGElementMetrics : public UserSpaceMetrics {
|
|||
return SVGContentUtils::GetFontSize(GetElementForType(aType));
|
||||
}
|
||||
float GetAxisLength(uint8_t aCtxType) const override;
|
||||
CSSSize GetCSSViewportSize() const override;
|
||||
|
||||
private:
|
||||
bool EnsureCtx() const;
|
||||
|
@ -89,6 +92,7 @@ class NonSVGFrameUserSpaceMetrics : public UserSpaceMetricsWithSize {
|
|||
|
||||
float GetEmLength(Type aType) const override;
|
||||
gfx::Size GetSize() const override;
|
||||
CSSSize GetCSSViewportSize() const override;
|
||||
|
||||
private:
|
||||
GeckoFontMetrics GetFontMetricsForType(Type aType) const override;
|
||||
|
|
|
@ -25,6 +25,10 @@ const unsigned short SVG_LENGTHTYPE_CH = 12;
|
|||
const unsigned short SVG_LENGTHTYPE_REM = 13;
|
||||
const unsigned short SVG_LENGTHTYPE_IC = 14;
|
||||
const unsigned short SVG_LENGTHTYPE_CAP = 15;
|
||||
const unsigned short SVG_LENGTHTYPE_VW = 16;
|
||||
const unsigned short SVG_LENGTHTYPE_VH = 17;
|
||||
const unsigned short SVG_LENGTHTYPE_VMIN = 18;
|
||||
const unsigned short SVG_LENGTHTYPE_VMAX = 19;
|
||||
|
||||
void SVGLength::GetValueAsString(nsAString& aValue) const {
|
||||
nsTextFormatter::ssprintf(aValue, u"%g", (double)mValue);
|
||||
|
@ -143,12 +147,6 @@ float SVGLength::GetValueInSpecifiedUnit(uint8_t aUnit,
|
|||
float userUnitsPerNewUnit =
|
||||
SVGLength(0.0f, aUnit).GetPixelsPerUnit(userSpaceMetrics, aAxis);
|
||||
|
||||
NS_ASSERTION(
|
||||
userUnitsPerCurrentUnit >= 0 || !std::isfinite(userUnitsPerCurrentUnit),
|
||||
"bad userUnitsPerCurrentUnit");
|
||||
NS_ASSERTION(userUnitsPerNewUnit >= 0 || !std::isfinite(userUnitsPerNewUnit),
|
||||
"bad userUnitsPerNewUnit");
|
||||
|
||||
float value = mValue * userUnitsPerCurrentUnit / userUnitsPerNewUnit;
|
||||
|
||||
// userUnitsPerCurrentUnit could be infinity, or userUnitsPerNewUnit could
|
||||
|
@ -182,6 +180,18 @@ float SVGLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics,
|
|||
return aMetrics.GetIcWidth(UserSpaceMetrics::Type::This);
|
||||
case SVG_LENGTHTYPE_CAP:
|
||||
return aMetrics.GetCapHeight(UserSpaceMetrics::Type::This);
|
||||
case SVG_LENGTHTYPE_VW:
|
||||
return aMetrics.GetCSSViewportSize().width / 100.f;
|
||||
case SVG_LENGTHTYPE_VH:
|
||||
return aMetrics.GetCSSViewportSize().height / 100.f;
|
||||
case SVG_LENGTHTYPE_VMIN: {
|
||||
auto sz = aMetrics.GetCSSViewportSize();
|
||||
return std::min(sz.width, sz.height) / 100.f;
|
||||
}
|
||||
case SVG_LENGTHTYPE_VMAX: {
|
||||
auto sz = aMetrics.GetCSSViewportSize();
|
||||
return std::max(sz.width, sz.height) / 100.f;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT(IsAbsoluteUnit(aUnitType));
|
||||
return GetAbsUnitsPerAbsUnit(SVG_LENGTHTYPE_PX, aUnitType);
|
||||
|
@ -234,6 +244,18 @@ nsCSSUnit SVGLength::SpecifiedUnitTypeToCSSUnit(uint8_t aSpecifiedUnit) {
|
|||
case SVG_LENGTHTYPE_CAP:
|
||||
return nsCSSUnit::eCSSUnit_CapHeight;
|
||||
|
||||
case SVG_LENGTHTYPE_VW:
|
||||
return nsCSSUnit::eCSSUnit_VW;
|
||||
|
||||
case SVG_LENGTHTYPE_VH:
|
||||
return nsCSSUnit::eCSSUnit_VH;
|
||||
|
||||
case SVG_LENGTHTYPE_VMIN:
|
||||
return nsCSSUnit::eCSSUnit_VMin;
|
||||
|
||||
case SVG_LENGTHTYPE_VMAX:
|
||||
return nsCSSUnit::eCSSUnit_VMax;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown unit type");
|
||||
return nsCSSUnit::eCSSUnit_Pixel;
|
||||
|
@ -288,6 +310,18 @@ void SVGLength::GetUnitString(nsAString& aUnit, uint16_t aUnitType) {
|
|||
case SVG_LENGTHTYPE_CAP:
|
||||
aUnit.AssignLiteral("cap");
|
||||
return;
|
||||
case SVG_LENGTHTYPE_VW:
|
||||
aUnit.AssignLiteral("vw");
|
||||
return;
|
||||
case SVG_LENGTHTYPE_VH:
|
||||
aUnit.AssignLiteral("vh");
|
||||
return;
|
||||
case SVG_LENGTHTYPE_VMIN:
|
||||
aUnit.AssignLiteral("vmin");
|
||||
return;
|
||||
case SVG_LENGTHTYPE_VMAX:
|
||||
aUnit.AssignLiteral("vmax");
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Unknown unit type! Someone's using an SVGLength "
|
||||
|
@ -341,6 +375,18 @@ uint16_t SVGLength::GetUnitTypeForString(const nsAString& aUnit) {
|
|||
if (aUnit.LowerCaseEqualsLiteral("cap")) {
|
||||
return SVG_LENGTHTYPE_CAP;
|
||||
}
|
||||
if (aUnit.LowerCaseEqualsLiteral("vw")) {
|
||||
return SVG_LENGTHTYPE_VW;
|
||||
}
|
||||
if (aUnit.LowerCaseEqualsLiteral("vh")) {
|
||||
return SVG_LENGTHTYPE_VH;
|
||||
}
|
||||
if (aUnit.LowerCaseEqualsLiteral("vmin")) {
|
||||
return SVG_LENGTHTYPE_VMIN;
|
||||
}
|
||||
if (aUnit.LowerCaseEqualsLiteral("vmax")) {
|
||||
return SVG_LENGTHTYPE_VMAX;
|
||||
}
|
||||
return SVG_LENGTHTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,12 +55,12 @@ enum nsCSSUnit : uint32_t {
|
|||
// different behavior than percent)
|
||||
|
||||
// Font relative measure
|
||||
eCSSUnit_EM = 800, // == current font size
|
||||
eCSSUnit_XHeight = 801, // distance from top of lower case x to
|
||||
// baseline
|
||||
eCSSUnit_Char = 802, // number of characters, used for width with
|
||||
// monospace font
|
||||
eCSSUnit_RootEM = 803, // == root element font size
|
||||
eCSSUnit_EM = 800, // == current font size
|
||||
eCSSUnit_XHeight = 801, // distance from top of lower case x to
|
||||
// baseline
|
||||
eCSSUnit_Char = 802, // number of characters, used for width with
|
||||
// monospace font
|
||||
eCSSUnit_RootEM = 803, // == root element font size
|
||||
eCSSUnit_Ideographic = 804, // == CJK water ideograph width
|
||||
eCSSUnit_CapHeight = 805, // == Capital letter height
|
||||
|
||||
|
@ -72,6 +72,12 @@ enum nsCSSUnit : uint32_t {
|
|||
eCSSUnit_Pica = 904, // 12 points == 16 CSS pixls
|
||||
eCSSUnit_Quarter = 905, // 96/101.6 CSS pixels
|
||||
eCSSUnit_Pixel = 906, // CSS pixel unit
|
||||
|
||||
// Viewport percentage lengths
|
||||
eCSSUnit_VW = 950,
|
||||
eCSSUnit_VH = 951,
|
||||
eCSSUnit_VMin = 952,
|
||||
eCSSUnit_VMax = 953,
|
||||
};
|
||||
|
||||
struct nsCSSValuePair;
|
||||
|
|
|
@ -5341,7 +5341,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
|
|||
use style::properties::PropertyDeclaration;
|
||||
use style::values::generics::length::{LengthPercentageOrAuto, Size};
|
||||
use style::values::generics::NonNegative;
|
||||
use style::values::specified::length::{FontRelativeLength, LengthPercentage};
|
||||
use style::values::specified::length::{FontRelativeLength, LengthPercentage, ViewportPercentageLength};
|
||||
use style::values::specified::FontSize;
|
||||
|
||||
let long = get_longhand_from_id!(property);
|
||||
|
@ -5375,6 +5375,18 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
|
|||
structs::nsCSSUnit::eCSSUnit_Point => NoCalcLength::Absolute(AbsoluteLength::Pt(value)),
|
||||
structs::nsCSSUnit::eCSSUnit_Pica => NoCalcLength::Absolute(AbsoluteLength::Pc(value)),
|
||||
structs::nsCSSUnit::eCSSUnit_Quarter => NoCalcLength::Absolute(AbsoluteLength::Q(value)),
|
||||
structs::nsCSSUnit::eCSSUnit_VW => {
|
||||
NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(value))
|
||||
},
|
||||
structs::nsCSSUnit::eCSSUnit_VH => {
|
||||
NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vh(value))
|
||||
},
|
||||
structs::nsCSSUnit::eCSSUnit_VMin => {
|
||||
NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmin(value))
|
||||
},
|
||||
structs::nsCSSUnit::eCSSUnit_VMax => {
|
||||
NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmax(value))
|
||||
},
|
||||
_ => unreachable!("Unknown unit passed to SetLengthValue"),
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>SVGLength with 'viewport' units</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/SVG/types.html#InterfaceSVGLength">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="ref"></div>
|
||||
<svg>
|
||||
<rect id="rect"/>
|
||||
</svg>
|
||||
<script>
|
||||
const units = ['vw', 'vh', 'vmin', 'vmax'];
|
||||
|
||||
for (const unit of units) {
|
||||
|
||||
const ref = document.getElementById("ref");
|
||||
ref.style.width=`10${unit}`;
|
||||
const rect = document.getElementById("rect");
|
||||
rect.setAttribute("x", `10${unit}`);
|
||||
|
||||
const ref_width = ref.offsetWidth;
|
||||
let length = rect.x.baseVal;
|
||||
|
||||
test(() => {
|
||||
assert_equals(length.unitType, SVGLength.SVG_LENGTHTYPE_UNKNOWN);
|
||||
assert_approx_equals(length.value, ref_width, 0.5);
|
||||
}, `${unit} unit in SVGLength`);
|
||||
|
||||
test(() => {
|
||||
const old_value = length.value
|
||||
length.value = ref_width * 2;
|
||||
assert_approx_equals(length.valueInSpecifiedUnits, 20, 0.2);
|
||||
length.value = old_value;
|
||||
}, `Convert back to ${unit} from new user unit value`);
|
||||
}
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче