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_bbox-with-invalid-viewBox.xhtml]
|
||||
[test_bbox.xhtml]
|
||||
[test_bbox-changes.xhtml]
|
||||
[test_bounds.html]
|
||||
[test_bug872812.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())
|
||||
return;
|
||||
|
||||
// If the rendering has changed, the bounds may well have changed too:
|
||||
aFrame->Properties().Delete(nsSVGUtils::ObjectBoundingBoxProperty());
|
||||
|
||||
nsSVGRenderingObserverList *observerList =
|
||||
GetObserverList(aFrame->GetContent()->AsElement());
|
||||
if (observerList) {
|
||||
@ -802,6 +805,12 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
||||
void
|
||||
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()) {
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aElement);
|
||||
if (observerList) {
|
||||
|
@ -903,6 +903,17 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
|
||||
!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
|
||||
return bbox;
|
||||
}
|
||||
|
||||
FrameProperties props = aFrame->Properties();
|
||||
|
||||
if (aFlags == eBBoxIncludeFillGeometry) {
|
||||
gfxRect* prop =
|
||||
static_cast<gfxRect*>(props.Get(ObjectBoundingBoxProperty()));
|
||||
if (prop) {
|
||||
return *prop;
|
||||
}
|
||||
}
|
||||
|
||||
gfxMatrix matrix;
|
||||
if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame ||
|
||||
aFrame->GetType() == nsGkAtoms::svgUseFrame) {
|
||||
@ -971,6 +982,13 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
|
||||
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 nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "nsColor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsISupportsBase.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsStyleStruct.h"
|
||||
@ -179,12 +180,20 @@ class nsSVGUtils
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
|
||||
typedef mozilla::gfx::AntialiasMode AntialiasMode;
|
||||
typedef mozilla::gfx::FillRule FillRule;
|
||||
typedef mozilla::gfx::GeneralPattern GeneralPattern;
|
||||
|
||||
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
|
||||
* must be an SVG frame. If aFrame is of type nsGkAtoms::svgOuterSVGFrame,
|
||||
@ -394,6 +403,8 @@ public:
|
||||
* aFrame's userspace.
|
||||
*/
|
||||
static gfxRect GetBBox(nsIFrame *aFrame,
|
||||
// If the default arg changes, update the handling for
|
||||
// ObjectBoundingBoxProperty() in the implementation.
|
||||
uint32_t aFlags = eBBoxIncludeFillGeometry);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user