+2017-10-24 Ryosuke Niwa <rniwa@webkit.org>
+
+ RenderSVGModelObject::checkIntersection triggers layout
+ https://bugs.webkit.org/show_bug.cgi?id=178710
+
+ Reviewed by Simon Fraser.
+
+ Added the support for SVG documents to js-test.js, and added a basic test for checkIntersection
+ and checkEnclosure using it.
+
+ * resources/js-test.js:
+ (ensureRootElement): Added. Creates a foreignObject element inside a SVG document.
+ (moveForeignObjectToTopIfNeeded): Added. In SVG, z-index order is determined by the element order.
+ In order to make the results visible, we move the foreignObject to the top by appending to the end
+ of the document element.
+ (getOrCreate):
+ (debug): Run innerHTML before appendChild as setting namespaceURI before running innerHTML would
+ result in span's being parsed as SVG elements.
+ (insertStyleSheet):
+ (finishJSTest):
+ * svg/custom/check-intersection-basic-expected.txt: Added.
+ * svg/custom/check-intersection-basic.svg: Added.
+
2017-10-24 Andy Estes <aestes@apple.com>
[Apple Pay] Implement a paymentmethodselected event for PaymentRequest
return document.createElement(tagName);
}
+ var rootElement = null;
+ function ensureRootElement()
+ {
+ if (!rootElement || !rootElement.isConnected) {
+ rootElement = document.body || document.documentElement;
+ if (document.documentElement.namespaceURI == 'http://www.w3.org/2000/svg') {
+ // FIXME: Make the test harness use SVG elements naively.
+ var foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
+ foreignObject.setAttribute('x', '0px');
+ foreignObject.setAttribute('y', '0px');
+ foreignObject.setAttribute('width', '100%');
+ foreignObject.setAttribute('height', '100%');
+ foreignObject.setAttribute('style', 'padding: 10px; background-color: rgba(255, 255, 255, 0.5)');
+ document.documentElement.appendChild(foreignObject);
+ rootElement = foreignObject;
+ }
+ }
+ return rootElement;
+ }
+
+ moveForeignObjectToTopIfNeeded = function () {
+ if (rootElement && rootElement.localName == 'foreignObject')
+ document.documentElement.appendChild(rootElement);
+ }
+
function getOrCreate(id, tagName)
{
var element = document.getElementById(id);
element = createHTMLElement(tagName);
element.id = id;
var refNode;
- var parent = document.body || document.documentElement;
+ var parent = ensureRootElement();
+
if (id == "description")
refNode = getOrCreate("console", "div");
else
debug = function debug(msg)
{
var span = createHTMLElement("span");
- getOrCreate("console", "div").appendChild(span); // insert it first so XHTML knows the namespace
span.innerHTML = msg + '<br />';
+ getOrCreate("console", "div").appendChild(span);
};
var css =
{
var styleElement = createHTMLElement("style");
styleElement.textContent = css;
- (document.head || document.documentElement).appendChild(styleElement);
+ (document.head || ensureRootElement()).appendChild(styleElement);
}
function handleTestFinished()
if (!self.wasPostTestScriptParsed)
return;
isSuccessfullyParsed();
+ moveForeignObjectToTopIfNeeded();
if (self.jsTestIsAsync && self.testRunner)
testRunner.notifyDone();
}
--- /dev/null
+Tests SVGSVGElement.checkIntersection
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS rectOfBox = createRect(10, 10, 50, 50); document.documentElement.checkIntersection(box, rectOfBox) is true
+PASS document.documentElement.checkEnclosure(box, rectOfBox) is true
+PASS rectInBox = createRect(20, 20, 20, 20); document.documentElement.checkIntersection(box, rectInBox) is true
+PASS document.documentElement.checkEnclosure(box, rectInBox) is false
+PASS boxExtendingUp = createRect(10, 0, 50, 60); document.documentElement.checkIntersection(box, boxExtendingUp) is true
+PASS document.documentElement.checkEnclosure(box, boxExtendingUp) is true
+PASS boxExtendingDown = createRect(10, 10, 50, 60); document.documentElement.checkIntersection(box, boxExtendingDown) is true
+PASS document.documentElement.checkEnclosure(box, boxExtendingDown) is true
+PASS boxExtendingLeft = createRect(0, 10, 60, 50); document.documentElement.checkIntersection(box, boxExtendingLeft) is true
+PASS document.documentElement.checkEnclosure(box, boxExtendingLeft) is true
+PASS boxExtendingRight = createRect(10, 10, 60, 50); document.documentElement.checkIntersection(box, boxExtendingRight) is true
+PASS document.documentElement.checkEnclosure(box, boxExtendingRight) is true
+PASS boxShrinkingTop = createRect(10, 20, 50, 40); document.documentElement.checkIntersection(box, boxShrinkingTop) is true
+PASS document.documentElement.checkEnclosure(box, boxShrinkingTop) is false
+PASS boxShrinkingBottom = createRect(10, 10, 50, 40); document.documentElement.checkIntersection(box, boxShrinkingBottom) is true
+PASS document.documentElement.checkEnclosure(box, boxShrinkingBottom) is false
+PASS boxShrinkingLeft = createRect(20, 10, 40, 50); document.documentElement.checkIntersection(box, boxShrinkingLeft) is true
+PASS document.documentElement.checkEnclosure(box, boxShrinkingLeft) is false
+PASS boxShrinkingRight = createRect(10, 10, 40, 50); document.documentElement.checkIntersection(box, boxShrinkingRight) is true
+PASS document.documentElement.checkEnclosure(box, boxShrinkingRight) is false
+PASS upperLeftCornerBox = createRect(5, 5, 20, 20); document.documentElement.checkIntersection(box, upperLeftCornerBox) is true
+PASS document.documentElement.checkEnclosure(box, upperLeftCornerBox) is false
+PASS upperRightCornerBox = createRect(45, 5, 20, 20); document.documentElement.checkIntersection(box, upperRightCornerBox) is true
+PASS document.documentElement.checkEnclosure(box, upperRightCornerBox) is false
+PASS boxOnTop = createRect(10, 5, 50, 5); document.documentElement.checkIntersection(box, boxOnTop) is false
+PASS document.documentElement.checkEnclosure(box, boxOnTop) is false
+PASS boxOnBottom = createRect(60, 5, 50, 5); document.documentElement.checkIntersection(box, boxOnBottom) is false
+PASS document.documentElement.checkEnclosure(box, boxOnBottom) is false
+PASS boxOnLeft = createRect(5, 10, 5, 50); document.documentElement.checkIntersection(box, boxOnLeft) is false
+PASS document.documentElement.checkEnclosure(box, boxOnLeft) is false
+PASS boxOnRight = createRect(60, 10, 5, 50); document.documentElement.checkIntersection(box, boxOnRight) is false
+PASS document.documentElement.checkEnclosure(box, boxOnRight) is false
+PASS box.setAttribute("class", "width20"); document.documentElement.checkIntersection(box, upperRightCornerBox) is false
+PASS narrowBox = createRect(10, 10, 20, 50); document.documentElement.checkEnclosure(box, narrowBox) is true
+PASS box.setAttribute("class", "width50"); document.documentElement.checkIntersection(box, upperRightCornerBox) is true
+PASS document.documentElement.checkEnclosure(box, narrowBox) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="runTest()">
+<script xlink:href="../../resources/js-test.js"/>
+<rect id="box" class="width50" x="10" y="10" height="50" fill="blue" />
+<text x="10" y="60"></text>
+<style>
+.width20 { width: 20px; }
+.width50 { width: 50px; }
+</style>
+<script>
+
+description('Tests SVGSVGElement.checkIntersection');
+
+function createRect(x, y, width, height) {
+ const rect = document.documentElement.createSVGRect();
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+ return rect;
+}
+
+function runTest() {
+ window.box = document.getElementById("box");
+
+ shouldBeTrue('rectOfBox = createRect(10, 10, 50, 50); document.documentElement.checkIntersection(box, rectOfBox)');
+ shouldBeTrue('document.documentElement.checkEnclosure(box, rectOfBox)');
+
+ shouldBeTrue('rectInBox = createRect(20, 20, 20, 20); document.documentElement.checkIntersection(box, rectInBox)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, rectInBox)');
+
+ shouldBeTrue('boxExtendingUp = createRect(10, 0, 50, 60); document.documentElement.checkIntersection(box, boxExtendingUp)');
+ shouldBeTrue('document.documentElement.checkEnclosure(box, boxExtendingUp)');
+
+ shouldBeTrue('boxExtendingDown = createRect(10, 10, 50, 60); document.documentElement.checkIntersection(box, boxExtendingDown)');
+ shouldBeTrue('document.documentElement.checkEnclosure(box, boxExtendingDown)');
+
+ shouldBeTrue('boxExtendingLeft = createRect(0, 10, 60, 50); document.documentElement.checkIntersection(box, boxExtendingLeft)');
+ shouldBeTrue('document.documentElement.checkEnclosure(box, boxExtendingLeft)');
+
+ shouldBeTrue('boxExtendingRight = createRect(10, 10, 60, 50); document.documentElement.checkIntersection(box, boxExtendingRight)');
+ shouldBeTrue('document.documentElement.checkEnclosure(box, boxExtendingRight)');
+
+ shouldBeTrue('boxShrinkingTop = createRect(10, 20, 50, 40); document.documentElement.checkIntersection(box, boxShrinkingTop)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxShrinkingTop)');
+
+ shouldBeTrue('boxShrinkingBottom = createRect(10, 10, 50, 40); document.documentElement.checkIntersection(box, boxShrinkingBottom)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxShrinkingBottom)');
+
+ shouldBeTrue('boxShrinkingLeft = createRect(20, 10, 40, 50); document.documentElement.checkIntersection(box, boxShrinkingLeft)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxShrinkingLeft)');
+
+ shouldBeTrue('boxShrinkingRight = createRect(10, 10, 40, 50); document.documentElement.checkIntersection(box, boxShrinkingRight)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxShrinkingRight)');
+
+ shouldBeTrue('upperLeftCornerBox = createRect(5, 5, 20, 20); document.documentElement.checkIntersection(box, upperLeftCornerBox)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, upperLeftCornerBox)');
+
+ shouldBeTrue('upperRightCornerBox = createRect(45, 5, 20, 20); document.documentElement.checkIntersection(box, upperRightCornerBox)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, upperRightCornerBox)');
+
+ shouldBeFalse('boxOnTop = createRect(10, 5, 50, 5); document.documentElement.checkIntersection(box, boxOnTop)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxOnTop)');
+
+ shouldBeFalse('boxOnBottom = createRect(60, 5, 50, 5); document.documentElement.checkIntersection(box, boxOnBottom)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxOnBottom)');
+
+ shouldBeFalse('boxOnLeft = createRect(5, 10, 5, 50); document.documentElement.checkIntersection(box, boxOnLeft)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxOnLeft)');
+
+ shouldBeFalse('boxOnRight = createRect(60, 10, 5, 50); document.documentElement.checkIntersection(box, boxOnRight)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, boxOnRight)');
+
+ shouldBeFalse('box.setAttribute("class", "width20"); document.documentElement.checkIntersection(box, upperRightCornerBox)');
+ shouldBeTrue('narrowBox = createRect(10, 10, 20, 50); document.documentElement.checkEnclosure(box, narrowBox)');
+
+ shouldBeTrue('box.setAttribute("class", "width50"); document.documentElement.checkIntersection(box, upperRightCornerBox)');
+ shouldBeFalse('document.documentElement.checkEnclosure(box, narrowBox)');
+
+ finishJSTest()
+}
+
+var successfullyParsed = true;
+
+</script>
+</svg>
+
+2017-10-24 Ryosuke Niwa <rniwa@webkit.org>
+
+ RenderSVGModelObject::checkIntersection triggers layout
+ https://bugs.webkit.org/show_bug.cgi?id=178710
+
+ Reviewed by Simon Fraser.
+
+ Fixed the bug that checkIntersection and checkEnclosure no longer updates the layout after r223882.
+
+ Test: svg/custom/check-intersection-basic.svg
+
+ * svg/SVGSVGElement.cpp:
+ (WebCore::SVGSVGElement::collectIntersectionOrEnclosureList):
+ (WebCore::SVGSVGElement::checkIntersection):
+ (WebCore::SVGSVGElement::checkEnclosure):
+ * svg/SVGSVGElement.h:
+
2017-10-24 Andy Estes <aestes@apple.com>
[Apple Pay] Implement a paymentmethodselected event for PaymentRequest
{
}
-Ref<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(SVGRect& rect, SVGElement* referenceElement, bool (*checkFunction)(const SVGElement*, SVGRect&))
+Ref<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(SVGRect& rect, SVGElement* referenceElement, bool (*checkFunction)(RefPtr<SVGElement>&&, SVGRect&))
{
Vector<Ref<Element>> elements;
for (auto& element : descendantsOfType<SVGElement>(referenceElement ? *referenceElement : *this)) {
return collectIntersectionOrEnclosureList(rect, referenceElement, checkEnclosure);
}
-bool SVGSVGElement::checkIntersection(const SVGElement* element, SVGRect& rect)
+bool SVGSVGElement::checkIntersection(RefPtr<SVGElement>&& element, SVGRect& rect)
{
- return element && RenderSVGModelObject::checkIntersection(element->renderer(), rect.propertyReference());
+ if (!element)
+ return false;
+ element->document().updateLayoutIgnorePendingStylesheets();
+ return RenderSVGModelObject::checkIntersection(element->renderer(), rect.propertyReference());
}
-bool SVGSVGElement::checkEnclosure(const SVGElement* element, SVGRect& rect)
+bool SVGSVGElement::checkEnclosure(RefPtr<SVGElement>&& element, SVGRect& rect)
{
- return element && RenderSVGModelObject::checkEnclosure(element->renderer(), rect.propertyReference());
+ if (!element)
+ return false;
+ element->document().updateLayoutIgnorePendingStylesheets();
+ return RenderSVGModelObject::checkEnclosure(element->renderer(), rect.propertyReference());
}
void SVGSVGElement::deselectAll()
Ref<NodeList> getIntersectionList(SVGRect&, SVGElement* referenceElement);
Ref<NodeList> getEnclosureList(SVGRect&, SVGElement* referenceElement);
- static bool checkIntersection(const SVGElement*, SVGRect&);
- static bool checkEnclosure(const SVGElement*, SVGRect&);
+ static bool checkIntersection(RefPtr<SVGElement>&&, SVGRect&);
+ static bool checkEnclosure(RefPtr<SVGElement>&&, SVGRect&);
void deselectAll();
static Ref<SVGNumber> createSVGNumber();
Frame* frameForCurrentScale() const;
void inheritViewAttributes(const SVGViewElement&);
- Ref<NodeList> collectIntersectionOrEnclosureList(SVGRect&, SVGElement*, bool (*checkFunction)(const SVGElement*, SVGRect&));
+ Ref<NodeList> collectIntersectionOrEnclosureList(SVGRect&, SVGElement*, bool (*checkFunction)(RefPtr<SVGElement>&&, SVGRect&));
bool m_useCurrentView { false };
SVGZoomAndPanType m_zoomAndPan { SVGZoomAndPanMagnify };