mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1159053 - Cache SVG getBBox and objectBoundingBox calculations for better performance. r=heycam
This commit is contained in:
parent
6e5096f6d3
commit
9922d273d9
@ -34,6 +34,7 @@ support-files =
|
|||||||
[test_animLengthUnits.xhtml]
|
[test_animLengthUnits.xhtml]
|
||||||
[test_bbox-with-invalid-viewBox.xhtml]
|
[test_bbox-with-invalid-viewBox.xhtml]
|
||||||
[test_bbox.xhtml]
|
[test_bbox.xhtml]
|
||||||
|
[test_bbox-changes.xhtml]
|
||||||
[test_bounds.html]
|
[test_bounds.html]
|
||||||
[test_bug872812.html]
|
[test_bug872812.html]
|
||||||
[test_getBBox-method.html]
|
[test_getBBox-method.html]
|
||||||
|
78
dom/svg/test/test_bbox-changes.xhtml
Normal file
78
dom/svg/test/test_bbox-changes.xhtml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1159053
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test that the results of getBBox update for changes</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<p id="display">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect id="rect1" x="10" y="10" width="10" height="10"/>
|
||||||
|
<rect id="rect2" x="30" y="10" width="10" height="10"/>
|
||||||
|
<g id="g">
|
||||||
|
<circle id="circle1" cx="60" cy="20" r="5"/>
|
||||||
|
<circle id="circle2" cx="120" cy="20" r="5"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="content" style="display: none"></div>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="application/javascript">//<![CDATA[
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
function init_and_run() {
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["svg.new-getBBox.enabled", true]]}, run);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkBBox(id, options, x, y, width, height, msg) {
|
||||||
|
var bbox = document.getElementById(id).getBBox(options);
|
||||||
|
is(bbox.x, x, id + ".getBBox().x" + msg);
|
||||||
|
is(bbox.y, y, id + ".getBBox().y" + msg);
|
||||||
|
is(bbox.width, width, id + ".getBBox().width" + msg);
|
||||||
|
is(bbox.height, height, id + ".getBBox().height" + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run()
|
||||||
|
{
|
||||||
|
// First call getBBox on 'rect1' with stroke included:
|
||||||
|
$("rect1").setAttribute("stroke", "black");
|
||||||
|
$("rect1").setAttribute("stroke-width", "10");
|
||||||
|
checkBBox("rect1", { fill:true, stroke:true }, 5, 5, 20, 20, " with stroke");
|
||||||
|
|
||||||
|
// Now remove the stroke from 'rect1' and check again:
|
||||||
|
$("rect1").removeAttribute("stroke");
|
||||||
|
$("rect1").removeAttribute("stroke-width");
|
||||||
|
checkBBox("rect1", { fill:true }, 10, 10, 10, 10, " after stroke removed");
|
||||||
|
|
||||||
|
// First call getBBox on 'rect2' without a stroke included:
|
||||||
|
checkBBox("rect2", { fill:true }, 30, 10, 10, 10, " with stroke");
|
||||||
|
|
||||||
|
// Now add a stroke to 'rect2' and check again:
|
||||||
|
$("rect2").setAttribute("stroke", "black");
|
||||||
|
$("rect2").setAttribute("stroke-width", "10");
|
||||||
|
checkBBox("rect2", { fill:true, stroke:true }, 25, 5, 20, 20, " with stroke");
|
||||||
|
|
||||||
|
// Check the initial result for getBBox on the group:
|
||||||
|
checkBBox("g", { fill:true }, 55, 15, 70, 10, " before child moves");
|
||||||
|
|
||||||
|
// Now move one of the circle children and check again:
|
||||||
|
$("circle2").setAttribute("cx", "110");
|
||||||
|
checkBBox("g", { fill:true }, 55, 15, 60, 10, " after child moves");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", init_and_run, false);
|
||||||
|
|
||||||
|
//]]></script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -778,6 +778,9 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
|||||||
if (!aFrame->GetContent()->IsElement())
|
if (!aFrame->GetContent()->IsElement())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// If the rendering has changed, the bounds may well have changed too:
|
||||||
|
aFrame->Properties().Delete(nsSVGUtils::ObjectBoundingBoxProperty());
|
||||||
|
|
||||||
nsSVGRenderingObserverList *observerList =
|
nsSVGRenderingObserverList *observerList =
|
||||||
GetObserverList(aFrame->GetContent()->AsElement());
|
GetObserverList(aFrame->GetContent()->AsElement());
|
||||||
if (observerList) {
|
if (observerList) {
|
||||||
@ -802,6 +805,12 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
|||||||
void
|
void
|
||||||
nsSVGEffects::InvalidateDirectRenderingObservers(Element *aElement, uint32_t aFlags /* = 0 */)
|
nsSVGEffects::InvalidateDirectRenderingObservers(Element *aElement, uint32_t aFlags /* = 0 */)
|
||||||
{
|
{
|
||||||
|
nsIFrame* frame = aElement->GetPrimaryFrame();
|
||||||
|
if (frame) {
|
||||||
|
// If the rendering has changed, the bounds may well have changed too:
|
||||||
|
frame->Properties().Delete(nsSVGUtils::ObjectBoundingBoxProperty());
|
||||||
|
}
|
||||||
|
|
||||||
if (aElement->HasRenderingObservers()) {
|
if (aElement->HasRenderingObservers()) {
|
||||||
nsSVGRenderingObserverList *observerList = GetObserverList(aElement);
|
nsSVGRenderingObserverList *observerList = GetObserverList(aElement);
|
||||||
if (observerList) {
|
if (observerList) {
|
||||||
|
@ -903,6 +903,17 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
|
|||||||
!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
|
!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameProperties props = aFrame->Properties();
|
||||||
|
|
||||||
|
if (aFlags == eBBoxIncludeFillGeometry) {
|
||||||
|
gfxRect* prop =
|
||||||
|
static_cast<gfxRect*>(props.Get(ObjectBoundingBoxProperty()));
|
||||||
|
if (prop) {
|
||||||
|
return *prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gfxMatrix matrix;
|
gfxMatrix matrix;
|
||||||
if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame ||
|
if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame ||
|
||||||
aFrame->GetType() == nsGkAtoms::svgUseFrame) {
|
aFrame->GetType() == nsGkAtoms::svgUseFrame) {
|
||||||
@ -971,6 +982,13 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
|
|||||||
bbox = gfxRect(0, 0, 0, 0);
|
bbox = gfxRect(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aFlags == eBBoxIncludeFillGeometry) {
|
||||||
|
// Obtaining the bbox for objectBoundingBox calculations is common so we
|
||||||
|
// cache the result for future calls, since calculation can be expensive:
|
||||||
|
props.Set(ObjectBoundingBoxProperty(), new gfxRect(bbox));
|
||||||
|
}
|
||||||
|
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
|
return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "nsColor.h"
|
#include "nsColor.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsID.h"
|
#include "nsID.h"
|
||||||
|
#include "nsIFrame.h"
|
||||||
#include "nsISupportsBase.h"
|
#include "nsISupportsBase.h"
|
||||||
#include "nsMathUtils.h"
|
#include "nsMathUtils.h"
|
||||||
#include "nsStyleStruct.h"
|
#include "nsStyleStruct.h"
|
||||||
@ -179,12 +180,20 @@ class nsSVGUtils
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef mozilla::dom::Element Element;
|
typedef mozilla::dom::Element Element;
|
||||||
|
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
|
||||||
typedef mozilla::gfx::AntialiasMode AntialiasMode;
|
typedef mozilla::gfx::AntialiasMode AntialiasMode;
|
||||||
typedef mozilla::gfx::FillRule FillRule;
|
typedef mozilla::gfx::FillRule FillRule;
|
||||||
typedef mozilla::gfx::GeneralPattern GeneralPattern;
|
typedef mozilla::gfx::GeneralPattern GeneralPattern;
|
||||||
|
|
||||||
static void Init();
|
static void Init();
|
||||||
|
|
||||||
|
static void DestroyObjectBoundingBoxProperty(void* aPropertyValue) {
|
||||||
|
delete static_cast<gfxRect*>(aPropertyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DECLARE_FRAME_PROPERTY(ObjectBoundingBoxProperty,
|
||||||
|
DestroyObjectBoundingBoxProperty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the nearest nsSVGInnerSVGFrame or nsSVGOuterSVGFrame frame. aFrame
|
* Gets the nearest nsSVGInnerSVGFrame or nsSVGOuterSVGFrame frame. aFrame
|
||||||
* must be an SVG frame. If aFrame is of type nsGkAtoms::svgOuterSVGFrame,
|
* must be an SVG frame. If aFrame is of type nsGkAtoms::svgOuterSVGFrame,
|
||||||
@ -394,6 +403,8 @@ public:
|
|||||||
* aFrame's userspace.
|
* aFrame's userspace.
|
||||||
*/
|
*/
|
||||||
static gfxRect GetBBox(nsIFrame *aFrame,
|
static gfxRect GetBBox(nsIFrame *aFrame,
|
||||||
|
// If the default arg changes, update the handling for
|
||||||
|
// ObjectBoundingBoxProperty() in the implementation.
|
||||||
uint32_t aFlags = eBBoxIncludeFillGeometry);
|
uint32_t aFlags = eBBoxIncludeFillGeometry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user