Bug 627594 - flush layout when working with percentage units r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D190270
This commit is contained in:
Robert Longson 2023-10-06 13:30:41 +00:00
Родитель d99400b65e
Коммит 850b5077f8
4 изменённых файлов: 47 добавлений и 26 удалений

Просмотреть файл

@ -149,9 +149,9 @@ float DOMSVGLength::GetValue(ErrorResult& aRv) {
Element()->FlushAnimations(); // May make HasOwner() == false
}
// If the unit depends on style then we need to flush before converting
// to pixels.
FlushStyleIfNeeded();
// If the unit depends on style or layout then we need to flush before
// converting to pixels.
FlushIfNeeded();
if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
SVGAnimatedLength* length = svg->GetAnimatedLength(mAttrEnum);
@ -184,9 +184,9 @@ void DOMSVGLength::SetValue(float aUserUnitValue, ErrorResult& aRv) {
return;
}
// If the unit depends on style then we need to flush before converting
// from pixels.
FlushStyleIfNeeded();
// If the unit depends on style or layout then we need to flush before
// converting from pixels.
FlushIfNeeded();
if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
aRv = svg->GetAnimatedLength(mAttrEnum)->SetBaseValue(aUserUnitValue, svg,
@ -446,13 +446,18 @@ SVGLength& DOMSVGLength::InternalItem() {
: alist->mBaseVal[mListIndex];
}
void DOMSVGLength::FlushStyleIfNeeded() {
void DOMSVGLength::FlushIfNeeded() {
auto MaybeFlush = [](uint16_t aUnitType, SVGElement* aSVGElement) {
if (!SVGLength::IsFontRelativeUnit(aUnitType)) {
FlushType flushType;
if (SVGLength::IsPercentageUnit(aUnitType)) {
flushType = FlushType::Layout;
} else if (SVGLength::IsFontRelativeUnit(aUnitType)) {
flushType = FlushType::Style;
} else {
return;
}
if (auto* currentDoc = aSVGElement->GetComposedDoc()) {
currentDoc->FlushPendingNotifications(FlushType::Style);
currentDoc->FlushPendingNotifications(flushType);
}
};

Просмотреть файл

@ -178,10 +178,10 @@ class DOMSVGLength final : public nsWrapperCache {
SVGLength& InternalItem();
/**
* Some values have units that depend on style so we may need to flush
* styles to ensure we get or set the right value in pixels.
* Some values have units that depend on style or layout so we may need to
* flush to ensure we get or set the right value in pixels.
*/
void FlushStyleIfNeeded();
void FlushIfNeeded();
#ifdef DEBUG
bool IndexIsValid();

Просмотреть файл

@ -93,9 +93,7 @@ class SVGLength {
float GetValueInSpecifiedUnit(uint8_t aUnit, const dom::SVGElement* aElement,
uint8_t aAxis) const;
bool IsPercentage() const {
return mUnit == dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
}
bool IsPercentage() const { return IsPercentageUnit(mUnit); }
float GetPixelsPerUnit(const dom::UserSpaceMetrics& aMetrics,
uint8_t aAxis) const {
@ -107,6 +105,10 @@ class SVGLength {
aUnitType <= dom::SVGLength_Binding::SVG_LENGTHTYPE_PC;
}
static bool IsPercentageUnit(uint8_t aUnit) {
return aUnit == dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
}
static bool IsAbsoluteUnit(uint8_t aUnit);
static bool IsFontRelativeUnit(uint8_t aUnit);

Просмотреть файл

@ -26,11 +26,11 @@ setup(function() {
function calculateXHeight() {
// Crude hack to calculate the x-height
var divElement = document.createElement("div");
let divElement = document.createElement("div");
divElement.setAttribute("style", "height: 1ex; font-size: 12px; font-family: Ahem;");
var pElement = document.querySelector("p");
let pElement = document.querySelector("p");
pElement.appendChild(divElement);
var xHeight = divElement.offsetHeight;
let xHeight = divElement.offsetHeight;
pElement.removeChild(divElement);
return xHeight;
}
@ -48,17 +48,31 @@ test(function() {
test(function() {
length.valueAsString = "3px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PERCENTAGE);
var referenceValue = 3 / svgWidth * 100;
let referenceValue = 3 / svgWidth * 100;
assert_equals(length.valueAsString, referenceValue + "%");
assert_equals(length.valueInSpecifiedUnits, referenceValue);
assert_equals(length.value, 3);
assert_equals(length.unitType, SVGLength.SVG_LENGTHTYPE_PERCENTAGE);
}, document.title + ", percentage");
test(function() {
let svgElement = document.getElementsByTagName("svg")[0];
let viewBox = svgElement.getAttribute("viewBox");
svgElement.removeAttribute("viewBox");
length.valueAsString = "50%";
let referenceValue = svgWidth / 2;
assert_equals(length.value, referenceValue);
svgElement.width.baseVal.value = 300;
referenceValue = svgElement.width.baseVal.value / 2;
assert_equals(length.value, referenceValue);
svgElement.width.baseVal.value = 150;
svgElement.setAttribute("viewBox", viewBox);
}, document.title + ", changing percentage basis");
test(function() {
length.valueAsString = "6px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_EMS);
var referenceValue = 6 / fontSize;
let referenceValue = 6 / fontSize;
assert_equals(length.valueAsString, referenceValue + "em");
assert_equals(length.valueInSpecifiedUnits, referenceValue);
assert_equals(length.value, 6);
@ -68,7 +82,7 @@ test(function() {
test(function() {
length.valueAsString = "2px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_EXS);
var referenceValue = 2 / xHeight;
let referenceValue = 2 / xHeight;
// Don't check valueAsString here, it's unreliable across browsers.
assert_approx_equals(length.valueInSpecifiedUnits, referenceValue, 0.1);
assert_approx_equals(length.value, 2.0, 0.1);
@ -89,7 +103,7 @@ test(function() {
test(function() {
length.valueAsString = "48px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_CM);
var referenceValue = 48 * 2.54 / cssPixelsPerInch;
let referenceValue = 48 * 2.54 / cssPixelsPerInch;
assert_equals(length.valueAsString, referenceValue.toFixed(2) + "cm");
assert_approx_equals(length.valueInSpecifiedUnits, referenceValue, 0.001);
assert_equals(length.value, 48);
@ -99,7 +113,7 @@ test(function() {
test(function() {
length.valueAsString = "48px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_MM);
var referenceValue = 48 * 25.4 / cssPixelsPerInch;
let referenceValue = 48 * 25.4 / cssPixelsPerInch;
assert_equals(length.valueAsString, referenceValue.toFixed(1) + "mm");
assert_approx_equals(length.valueInSpecifiedUnits, referenceValue, 0.001);
assert_equals(length.value, 48);
@ -109,7 +123,7 @@ test(function() {
test(function() {
length.valueAsString = "48px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_IN);
var referenceValue = 48 / cssPixelsPerInch;
let referenceValue = 48 / cssPixelsPerInch;
assert_equals(length.valueAsString, referenceValue + "in");
assert_equals(length.valueInSpecifiedUnits, referenceValue);
assert_equals(length.value, 48);
@ -119,7 +133,7 @@ test(function() {
test(function() {
length.valueAsString = "4px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PT);
var referenceValue = 4 / cssPixelsPerInch * 72;
let referenceValue = 4 / cssPixelsPerInch * 72;
assert_equals(length.valueAsString, referenceValue + "pt");
assert_equals(length.valueInSpecifiedUnits, referenceValue);
assert_equals(length.value, 4);
@ -129,7 +143,7 @@ test(function() {
test(function() {
length.valueAsString = "16px";
length.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PC);
var referenceValue = 16 / cssPixelsPerInch * 6;
let referenceValue = 16 / cssPixelsPerInch * 6;
// Don't check valueAsString here, it's unreliable across browsers.
assert_equals(length.valueInSpecifiedUnits, referenceValue);
assert_equals(length.value, 16);