Bug 1398806 - GetCtx and GetNearestViewport should return the nearest svg or symbol element which is now an SVGViewportElement rather than only returning the nearest svg element because a symbol establishes a viewport too. r=dholbert

This commit is contained in:
Robert Longson 2017-10-10 07:58:34 +01:00
parent 3c25329700
commit 0e21ecb9e3
19 changed files with 68 additions and 50 deletions

View File

@ -374,8 +374,8 @@ SVGContentUtils::EstablishesViewport(nsIContent *aContent)
nsGkAtoms::symbol);
}
nsSVGElement*
SVGContentUtils::GetNearestViewportElement(nsIContent *aContent)
SVGViewportElement*
SVGContentUtils::GetNearestViewportElement(const nsIContent *aContent)
{
nsIContent *element = aContent->GetFlattenedTreeParent();
@ -384,7 +384,11 @@ SVGContentUtils::GetNearestViewportElement(nsIContent *aContent)
if (element->IsSVGElement(nsGkAtoms::foreignObject)) {
return nullptr;
}
return static_cast<nsSVGElement*>(element);
MOZ_ASSERT(element->IsAnyOfSVGElements(nsGkAtoms::svg,
nsGkAtoms::symbol),
"upcoming static_cast is only valid for "
"SVGViewportElement subclasses");
return static_cast<SVGViewportElement*>(element);
}
element = element->GetFlattenedTreeParent();
}
@ -828,7 +832,7 @@ SVGContentUtils::CoordToFloat(nsSVGElement *aContent,
return nsPresContext::AppUnitsToFloatCSSPixels(aCoord.GetCoordValue());
case eStyleUnit_Percent: {
SVGSVGElement* ctx = aContent->GetCtx();
SVGViewportElement* ctx = aContent->GetCtx();
return ctx ? aCoord.GetPercentValue() * ctx->GetLength(SVGContentUtils::XY) : 0.0f;
}
default:

View File

@ -32,6 +32,7 @@ class SVGPreserveAspectRatio;
namespace dom {
class Element;
class SVGSVGElement;
class SVGViewportElement;
} // namespace dom
} // namespace mozilla
@ -238,8 +239,8 @@ public:
*/
static bool EstablishesViewport(nsIContent *aContent);
static nsSVGElement*
GetNearestViewportElement(nsIContent *aContent);
static mozilla::dom::SVGViewportElement*
GetNearestViewportElement(const nsIContent *aContent);
/* enum for specifying coordinate direction for ObjectSpace/UserSpace */
enum ctxDirection { X, Y, XY };

View File

@ -173,7 +173,7 @@ SVGLength::GetUserUnitsPerUnit(const nsSVGElement *aElement, uint8_t aAxis) cons
SVGLength::GetUserUnitsPerPercent(const nsSVGElement *aElement, uint8_t aAxis)
{
if (aElement) {
dom::SVGSVGElement *viewportElement = aElement->GetCtx();
dom::SVGViewportElement *viewportElement = aElement->GetCtx();
if (viewportElement) {
return std::max(viewportElement->GetLength(aAxis) / 100.0f, 0.0f);
}

View File

@ -250,7 +250,7 @@ SVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsAtom* aName,
// nsSVGElement methods
void
SVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext)
SVGMarkerElement::SetParentCoordCtxProvider(SVGViewportElement *aContext)
{
mCoordCtx = aContext;
mViewBoxToViewportTransform = nullptr;

View File

@ -153,7 +153,7 @@ protected:
const nsAString& aValue,
nsAttrValue& aResult) override;
void SetParentCoordCtxProvider(SVGSVGElement *aContext);
void SetParentCoordCtxProvider(SVGViewportElement *aContext);
virtual LengthAttributesInfo GetLengthInfo() override;
virtual AngleAttributesInfo GetAngleInfo() override;
@ -180,7 +180,7 @@ protected:
// derived properties (from 'orient') handled separately
nsSVGOrientType mOrientType;
SVGSVGElement *mCoordCtx;
SVGViewportElement* mCoordCtx;
nsAutoPtr<gfx::Matrix> mViewBoxToViewportTransform;
};

View File

@ -182,15 +182,6 @@ public:
// SVG-as-an-image documents.)
virtual void FlushImageTransformInvalidation();
svgFloatSize GetViewportSize() const {
return svgFloatSize(mViewportWidth, mViewportHeight);
}
void SetViewportSize(const svgFloatSize& aSize) {
mViewportWidth = aSize.width;
mViewportHeight = aSize.height;
}
private:
// SVGViewportElement methods:

View File

@ -127,6 +127,15 @@ public:
gfx::Matrix GetViewBoxTransform() const;
svgFloatSize GetViewportSize() const {
return svgFloatSize(mViewportWidth, mViewportHeight);
}
void SetViewportSize(const svgFloatSize& aSize) {
mViewportWidth = aSize.width;
mViewportHeight = aSize.height;
}
// WebIDL
already_AddRefed<SVGAnimatedRect> ViewBox();
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();

View File

@ -1109,7 +1109,20 @@ nsSVGElement::GetOwnerSVGElement(nsIDOMSVGElement * *aOwnerSVGElement)
SVGSVGElement*
nsSVGElement::GetOwnerSVGElement()
{
return GetCtx(); // this may return nullptr
nsIContent* ancestor = GetFlattenedTreeParent();
while (ancestor && ancestor->IsSVGElement()) {
if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
return nullptr;
}
if (ancestor->IsSVGElement(nsGkAtoms::svg)) {
return static_cast<SVGSVGElement*>(ancestor);
}
ancestor = ancestor->GetFlattenedTreeParent();
}
// we don't have an ancestor <svg> element...
return nullptr;
}
NS_IMETHODIMP
@ -1545,23 +1558,10 @@ nsAtom* nsSVGElement::GetEventNameForAttr(nsAtom* aAttr)
return aAttr;
}
SVGSVGElement *
SVGViewportElement *
nsSVGElement::GetCtx() const
{
nsIContent* ancestor = GetFlattenedTreeParent();
while (ancestor && ancestor->IsSVGElement()) {
if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
return nullptr;
}
if (ancestor->IsSVGElement(nsGkAtoms::svg)) {
return static_cast<SVGSVGElement*>(ancestor);
}
ancestor = ancestor->GetFlattenedTreeParent();
}
// we don't have an ancestor <svg> element...
return nullptr;
return SVGContentUtils::GetNearestViewportElement(this);
}
/* virtual */ gfxMatrix
@ -1660,7 +1660,7 @@ nsSVGElement::GetAnimatedLengthValues(float *aFirst, ...)
NS_ASSERTION(info.mLengthCount > 0,
"GetAnimatedLengthValues on element with no length attribs");
SVGSVGElement *ctx = nullptr;
SVGViewportElement *ctx = nullptr;
float *f = aFirst;
uint32_t i = 0;

View File

@ -44,6 +44,7 @@ class DeclarationBlock;
namespace dom {
class SVGSVGElement;
class SVGViewportElement;
static const unsigned short SVG_UNIT_TYPE_UNKNOWN = 0;
static const unsigned short SVG_UNIT_TYPE_USERSPACEONUSE = 1;
@ -145,7 +146,7 @@ public:
// Gets the element that establishes the rectangular viewport against which
// we should resolve percentage lengths (our "coordinate context"). Returns
// nullptr for outer <svg> or SVG without an <svg> parent (invalid SVG).
mozilla::dom::SVGSVGElement* GetCtx() const;
mozilla::dom::SVGViewportElement* GetCtx() const;
/**
* Returns aMatrix pre-multiplied by (explicit or implicit) transforms that

View File

@ -121,7 +121,7 @@
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "RegionBuilder.h"
#include "SVGSVGElement.h"
#include "SVGViewportElement.h"
#include "DisplayItemClip.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "prenv.h"
@ -9764,7 +9764,7 @@ ComputeSVGReferenceRect(nsIFrame* aFrame,
case StyleGeometryBox::ViewBox: {
nsIContent* content = aFrame->GetContent();
nsSVGElement* element = static_cast<nsSVGElement*>(content);
SVGSVGElement* svgElement = element->GetCtx();
SVGViewportElement* svgElement = element->GetCtx();
MOZ_ASSERT(svgElement);
if (svgElement && svgElement->HasViewBoxRect()) {

View File

@ -531,6 +531,7 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-re
== viewBox-and-pattern-02.svg pass.svg
== viewBox-and-pattern-03.svg pass.svg
== viewBox-and-pattern-04.svg pass.svg
== viewBox-and-symbol-01.svg pass.svg
== viewBox-invalid-01.svg pass.svg
== viewBox-invalid-02.svg pass.svg
== viewBox-valid-01.svg pass.svg

View File

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="mySymbol" viewBox="0 0 20 20">
<rect fill="lime" x="50%" height="20px" width="3%"/>
</symbol>
</defs>
<rect width="100%" height="100%" fill="lime"/>
<svg viewBox="0 0 20 20">
<rect fill="red" x="50%" height="20px" width="2%"/>
</svg>
<svg>
<use href="#mySymbol"/>
</svg>
</svg>

After

Width:  |  Height:  |  Size: 374 B

View File

@ -9,7 +9,6 @@
#include "gfx2DGlue.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/ShapeUtils.h"

View File

@ -16,7 +16,6 @@
#include "nsLayoutUtils.h"
#include "imgINotificationObserver.h"
#include "SVGObserverUtils.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "nsSVGUtils.h"
#include "SVGContentUtils.h"
#include "SVGGeometryFrame.h"

View File

@ -17,7 +17,6 @@
#include "nsLayoutUtils.h"
#include "imgINotificationObserver.h"
#include "SVGObserverUtils.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "nsSVGUtils.h"
#include "SVGContentUtils.h"
#include "SVGGeometryFrame.h"

View File

@ -194,7 +194,7 @@ nsSVGMarkerFrame::GetMarkBBoxContribution(const Matrix& aToBBoxUserspace,
}
void
nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGSVGElement *aContext)
nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGViewportElement *aContext)
{
SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(GetContent());
marker->SetParentCoordCtxProvider(aContext);
@ -219,7 +219,7 @@ nsSVGMarkerFrame::AutoMarkerReferencer::AutoMarkerReferencer(
mFrame->mInUse = true;
mFrame->mMarkedFrame = aMarkedFrame;
SVGSVGElement *ctx =
SVGViewportElement *ctx =
static_cast<nsSVGElement*>(aMarkedFrame->GetContent())->GetCtx();
mFrame->SetParentCoordCtxProvider(ctx);
}

View File

@ -20,7 +20,7 @@ class gfxContext;
namespace mozilla {
class SVGGeometryFrame;
namespace dom {
class SVGSVGElement;
class SVGViewportElement;
} // namespace dom
} // namespace mozilla
@ -118,7 +118,7 @@ private:
};
// nsSVGMarkerFrame methods:
void SetParentCoordCtxProvider(mozilla::dom::SVGSVGElement *aContext);
void SetParentCoordCtxProvider(mozilla::dom::SVGViewportElement *aContext);
// recursion prevention flag
bool mInUse;

View File

@ -660,7 +660,7 @@ nsSVGPatternFrame::ConstructCTM(const nsSVGViewBox& aViewBox,
const Matrix &callerCTM,
nsIFrame *aTarget)
{
SVGSVGElement *ctx = nullptr;
SVGViewportElement *ctx = nullptr;
nsIContent* targetContent = aTarget->GetContent();
gfxFloat scaleX, scaleY;

View File

@ -49,7 +49,7 @@
#include "SVGGeometryElement.h"
#include "SVGGeometryFrame.h"
#include "nsSVGPaintServerFrame.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/dom/SVGViewportElement.h"
#include "nsTextFrame.h"
#include "SVGContentUtils.h"
#include "SVGTextFrame.h"
@ -290,7 +290,7 @@ nsSVGUtils::GetContextSize(const nsIFrame* aFrame)
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "bad cast");
const nsSVGElement* element = static_cast<nsSVGElement*>(aFrame->GetContent());
SVGSVGElement* ctx = element->GetCtx();
SVGViewportElement* ctx = element->GetCtx();
if (ctx) {
size.width = ctx->GetLength(SVGContentUtils::X);
size.height = ctx->GetLength(SVGContentUtils::Y);
@ -323,7 +323,7 @@ nsSVGUtils::ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength)
// Multiply first to avoid precision errors:
return axis * aLength->GetAnimValInSpecifiedUnits() / 100;
}
return aLength->GetAnimValue(static_cast<SVGSVGElement*>(nullptr)) * axis;
return aLength->GetAnimValue(static_cast<SVGViewportElement*>(nullptr)) * axis;
}
float