Bug 272288 Patch 2: Store override preserveAspectRatio values in property table on image document's root node, when painting <svg> image element. r=roc a=roc
--HG-- rename : layout/reftests/svg/image/blueRect10x10.svg => layout/reftests/svg/image/blueRect10x10-viewBox.svg rename : layout/reftests/svg/image/image-preserveAspectRatio-01.svg => layout/reftests/svg/image/image-preserveAspectRatio-01-raster.svg rename : layout/reftests/svg/image/image-preserveAspectRatio-01.svg => layout/reftests/svg/image/image-preserveAspectRatio-01-svg.svg rename : layout/reftests/svg/image/image-preserveAspectRatio-02.svg => layout/reftests/svg/image/image-preserveAspectRatio-02-raster.svg rename : layout/reftests/svg/image/image-preserveAspectRatio-02.svg => layout/reftests/svg/image/image-preserveAspectRatio-02-svg.svg
|
@ -1245,6 +1245,7 @@ GK_ATOM(opacity, "opacity")
|
|||
GK_ATOM(_operator, "operator")
|
||||
GK_ATOM(out, "out")
|
||||
GK_ATOM(over, "over")
|
||||
GK_ATOM(overridePreserveAspectRatio, "overridePreserveAspectRatio")
|
||||
GK_ATOM(pad, "pad")
|
||||
GK_ATOM(path, "path")
|
||||
GK_ATOM(pathLength, "pathLength")
|
||||
|
|
|
@ -115,6 +115,8 @@ public:
|
|||
{ return mBaseVal; }
|
||||
const SVGPreserveAspectRatio &GetAnimValue() const
|
||||
{ return mAnimVal; }
|
||||
PRBool IsAnimated() const
|
||||
{ return mIsAnimated; }
|
||||
|
||||
nsresult ToDOMAnimatedPreserveAspectRatio(
|
||||
nsIDOMSVGAnimatedPreserveAspectRatio **aResult,
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGSVGElement.h"
|
||||
#include "nsSVGEffects.h" // For nsSVGEffects::RemoveAllRenderingObservers
|
||||
#include "nsContentErrors.h" // For NS_PROPTABLE_PROP_OVERWRITTEN
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
#include "nsEventDispatcher.h"
|
||||
|
@ -212,6 +213,7 @@ nsSVGSVGElement::nsSVGSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
|||
#ifdef MOZ_SMIL
|
||||
, mStartAnimationOnBindToTree(!aFromParser)
|
||||
#endif // MOZ_SMIL
|
||||
, mNeedsPreserveAspectRatioFlush(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -994,11 +996,16 @@ nsSVGSVGElement::GetViewBoxTransform()
|
|||
return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
|
||||
}
|
||||
|
||||
// Do we have an override preserveAspectRatio value?
|
||||
const SVGPreserveAspectRatio* overridePARPtr =
|
||||
GetImageOverridePreserveAspectRatio();
|
||||
|
||||
return nsSVGUtils::GetViewBoxTransform(this,
|
||||
viewportWidth, viewportHeight,
|
||||
viewBox.x, viewBox.y,
|
||||
viewBox.width, viewBox.height,
|
||||
mPreserveAspectRatio);
|
||||
overridePARPtr ? *overridePARPtr :
|
||||
mPreserveAspectRatio.GetAnimValue());
|
||||
}
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
|
@ -1100,6 +1107,13 @@ nsSVGSVGElement::InvalidateTransformNotifyFrame()
|
|||
#endif
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGSVGElement::HasPreserveAspectRatio()
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::preserveAspectRatio) ||
|
||||
mPreserveAspectRatio.IsAnimated();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsSVGSVGElement
|
||||
|
||||
|
@ -1242,3 +1256,85 @@ nsSVGSVGElement::RemoveAllRenderingObservers()
|
|||
nsSVGEffects::RemoveAllRenderingObservers(this);
|
||||
}
|
||||
#endif // !MOZ_LIBXUL
|
||||
|
||||
// Callback function, for freeing PRUint64 values stored in property table
|
||||
static void
|
||||
ReleasePreserveAspectRatioPropertyValue(void* aObject, /* unused */
|
||||
nsIAtom* aPropertyName, /* unused */
|
||||
void* aPropertyValue,
|
||||
void* aData /* unused */)
|
||||
{
|
||||
SVGPreserveAspectRatio* valPtr =
|
||||
static_cast<SVGPreserveAspectRatio*>(aPropertyValue);
|
||||
delete valPtr;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGSVGElement::
|
||||
SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
|
||||
"should only override preserveAspectRatio in images");
|
||||
#endif
|
||||
|
||||
if (!mViewBox.IsValid()) {
|
||||
return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
|
||||
}
|
||||
|
||||
if (aPAR.GetDefer() && HasPreserveAspectRatio()) {
|
||||
return; // Referring element defers to my own preserveAspectRatio value.
|
||||
}
|
||||
|
||||
SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR);
|
||||
nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio,
|
||||
pAROverridePtr,
|
||||
ReleasePreserveAspectRatioPropertyValue);
|
||||
NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
|
||||
"Setting override value when it's already set...?");
|
||||
|
||||
if (NS_LIKELY(NS_SUCCEEDED(rv))) {
|
||||
mNeedsPreserveAspectRatioFlush = PR_TRUE;
|
||||
} else {
|
||||
// property-insertion failed (e.g. OOM in property-table code)
|
||||
delete pAROverridePtr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGSVGElement::ClearImageOverridePreserveAspectRatio()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
|
||||
"should only override preserveAspectRatio in images");
|
||||
#endif
|
||||
|
||||
void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio);
|
||||
if (valPtr) {
|
||||
mNeedsPreserveAspectRatioFlush = PR_TRUE;
|
||||
delete static_cast<SVGPreserveAspectRatio*>(valPtr);
|
||||
}
|
||||
}
|
||||
|
||||
const SVGPreserveAspectRatio*
|
||||
nsSVGSVGElement::GetImageOverridePreserveAspectRatio()
|
||||
{
|
||||
void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio);
|
||||
#ifdef DEBUG
|
||||
if (valPtr) {
|
||||
NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
|
||||
"should only override preserveAspectRatio in images");
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<SVGPreserveAspectRatio*>(valPtr);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGSVGElement::FlushPreserveAspectRatioOverride()
|
||||
{
|
||||
if (mNeedsPreserveAspectRatioFlush) {
|
||||
InvalidateTransformNotifyFrame();
|
||||
mNeedsPreserveAspectRatioFlush = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ class nsSVGSVGElement : public nsSVGSVGElementBase,
|
|||
{
|
||||
friend class nsSVGOuterSVGFrame;
|
||||
friend class nsSVGInnerSVGFrame;
|
||||
friend class nsSVGImageFrame;
|
||||
|
||||
protected:
|
||||
friend nsresult NS_NewSVGSVGElement(nsIContent **aResult,
|
||||
|
@ -140,6 +141,7 @@ protected:
|
|||
|
||||
public:
|
||||
typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
|
||||
typedef mozilla::SVGPreserveAspectRatio SVGPreserveAspectRatio;
|
||||
|
||||
// interfaces:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -210,6 +212,10 @@ public:
|
|||
gfxMatrix GetViewBoxTransform();
|
||||
PRBool HasValidViewbox() const { return mViewBox.IsValid(); }
|
||||
|
||||
// This flushes any pending notifications for a preserveAspectRatio override
|
||||
// in this document. (Only applicable in SVG-as-an-image documents.)
|
||||
virtual void FlushPreserveAspectRatioOverride();
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
svgFloatSize GetViewportSize() const {
|
||||
|
@ -230,6 +236,14 @@ public:
|
|||
virtual void RemoveAllRenderingObservers();
|
||||
#endif // !MOZ_LIBXUL
|
||||
|
||||
private:
|
||||
// Methods for <image> elements to override my "PreserveAspectRatio" value.
|
||||
// These are private so that only our friends (nsSVGImageFrame in
|
||||
// particular) have access.
|
||||
void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
|
||||
void ClearImageOverridePreserveAspectRatio();
|
||||
const SVGPreserveAspectRatio* GetImageOverridePreserveAspectRatio();
|
||||
|
||||
protected:
|
||||
// nsSVGElement overrides
|
||||
PRBool IsEventName(nsIAtom* aName);
|
||||
|
@ -267,6 +281,11 @@ protected:
|
|||
// invalidate viewbox -> viewport xform & inform frames
|
||||
void InvalidateTransformNotifyFrame();
|
||||
|
||||
// Returns PR_TRUE if we have at least one of the following:
|
||||
// - a (valid or invalid) value for the preserveAspectRatio attribute
|
||||
// - a SMIL-animated value for the preserveAspectRatio attribute
|
||||
PRBool HasPreserveAspectRatio();
|
||||
|
||||
virtual LengthAttributesInfo GetLengthInfo();
|
||||
|
||||
enum { X, Y, WIDTH, HEIGHT };
|
||||
|
@ -320,6 +339,7 @@ protected:
|
|||
// to manually kick off animation when they are bound to the tree.
|
||||
PRPackedBool mStartAnimationOnBindToTree;
|
||||
#endif // MOZ_SMIL
|
||||
PRPackedBool mNeedsPreserveAspectRatioFlush;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<!-- Helper SVG file used by some reftests -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="root"
|
||||
viewBox="0 0 10 10">
|
||||
<rect x="0" y="0" width="10" height="10" fill="blue"/>
|
||||
<rect x="1" y="1" width="8" height="8" fill="lightblue"/>
|
||||
<rect x="1" y="1" width="8" height="4" fill="teal"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 322 B |
До Ширина: | Высота: | Размер: 572 B После Ширина: | Высота: | Размер: 572 B |
|
@ -0,0 +1,12 @@
|
|||
<!-- Test to make sure "preserveAspectRatio" value is applied correctly on
|
||||
<image> tag, when the width:height ratio is less than the image's
|
||||
nativeWidth:nativeHeight -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<script xlink:href="util.js" type="text/javascript"/>
|
||||
<script>
|
||||
var grid = generateImageGrid("blueRect10x10-viewBox.svg", 20, 40);
|
||||
grid.setAttribute("transform", "translate(10, 10)");
|
||||
document.documentElement.appendChild(grid);
|
||||
</script>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 533 B |
До Ширина: | Высота: | Размер: 575 B После Ширина: | Высота: | Размер: 575 B |
|
@ -0,0 +1,12 @@
|
|||
<!-- Test to make sure "preserveAspectRatio" value is applied correctly on
|
||||
<image> tag, when the width:height ratio is greater than the image's
|
||||
nativeWidth:nativeHeight -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<script xlink:href="util.js" type="text/javascript"/>
|
||||
<script>
|
||||
var grid = generateImageGrid("blueRect10x10-viewBox.svg", 40, 20);
|
||||
grid.setAttribute("transform", "translate(10, 10)");
|
||||
document.documentElement.appendChild(grid);
|
||||
</script>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 536 B |
|
@ -21,5 +21,7 @@
|
|||
# Tests for <image> with preserveAspectRatio
|
||||
# NOTE: The reference cases in the following tests trigger 20 assertions each
|
||||
# (1 per <symbol> element), due to bug 563481.
|
||||
asserts(20) == image-preserveAspectRatio-01.svg image-preserveAspectRatio-01-ref.svg
|
||||
asserts(20) == image-preserveAspectRatio-02.svg image-preserveAspectRatio-02-ref.svg
|
||||
asserts(20) == image-preserveAspectRatio-01-raster.svg image-preserveAspectRatio-01-ref.svg
|
||||
asserts(20) == image-preserveAspectRatio-01-svg.svg image-preserveAspectRatio-01-ref.svg
|
||||
asserts(20) == image-preserveAspectRatio-02-raster.svg image-preserveAspectRatio-02-ref.svg
|
||||
asserts(20) == image-preserveAspectRatio-02-svg.svg image-preserveAspectRatio-02-ref.svg
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "gfxMatrix.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsSVGSVGElement.h"
|
||||
|
||||
class nsSVGImageFrame;
|
||||
|
||||
|
@ -263,8 +264,8 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
|
|||
return NS_OK;
|
||||
|
||||
float x, y, width, height;
|
||||
nsSVGElement *element = static_cast<nsSVGElement*>(mContent);
|
||||
element->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
|
||||
nsSVGImageElement *imgElem = static_cast<nsSVGImageElement*>(mContent);
|
||||
imgElem->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
|
||||
if (width <= 0 || height <= 0)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -320,6 +321,26 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
|
|||
PRUint32 drawFlags = imgIContainer::FLAG_SYNC_DECODE;
|
||||
|
||||
if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) {
|
||||
nsIFrame* imgRootFrame = mImageContainer->GetRootLayoutFrame();
|
||||
if (!imgRootFrame) {
|
||||
// bad image (e.g. XML parse error in image's SVG file)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Grab root node (w/ sanity-check to make sure it exists & is <svg>)
|
||||
nsSVGSVGElement* rootSVGElem =
|
||||
static_cast<nsSVGSVGElement*>(imgRootFrame->GetContent());
|
||||
if (!rootSVGElem || rootSVGElem->GetNameSpaceID() != kNameSpaceID_SVG ||
|
||||
rootSVGElem->Tag() != nsGkAtoms::svg) {
|
||||
NS_ABORT_IF_FALSE(PR_FALSE, "missing or non-<svg> root node!!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Override preserveAspectRatio in our helper document
|
||||
// XXXdholbert We should technically be overriding the helper doc's clip
|
||||
// and overflow properties here, too. See bug 272288 comment 36.
|
||||
rootSVGElem->SetImageOverridePreserveAspectRatio(
|
||||
imgElem->mPreserveAspectRatio.GetAnimValue());
|
||||
nsRect destRect(0, 0,
|
||||
appUnitsPerDevPx * width,
|
||||
appUnitsPerDevPx * height);
|
||||
|
@ -334,6 +355,8 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
|
|||
destRect,
|
||||
aDirtyRect ? dirtyRect : destRect,
|
||||
drawFlags);
|
||||
|
||||
rootSVGElem->ClearImageOverridePreserveAspectRatio();
|
||||
} else { // mImageContainer->GetType() == TYPE_RASTER
|
||||
nsLayoutUtils::DrawSingleUnscaledImage(
|
||||
aContext->GetRenderingContext(this),
|
||||
|
|
|
@ -166,6 +166,21 @@ SVGDocumentWrapper::UpdateViewportBounds(const nsIntSize& aViewportSize)
|
|||
mIgnoreInvalidation = PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
SVGDocumentWrapper::FlushPreserveAspectRatioOverride()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mIgnoreInvalidation, "shouldn't be reentrant");
|
||||
|
||||
nsSVGSVGElement* svgElem = GetRootSVGElem();
|
||||
if (!svgElem)
|
||||
return;
|
||||
|
||||
mIgnoreInvalidation = PR_TRUE;
|
||||
svgElem->FlushPreserveAspectRatioOverride();
|
||||
FlushLayout();
|
||||
mIgnoreInvalidation = PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
SVGDocumentWrapper::IsAnimated()
|
||||
{
|
||||
|
|
|
@ -138,6 +138,14 @@ public:
|
|||
*/
|
||||
void UpdateViewportBounds(const nsIntSize& aViewportSize);
|
||||
|
||||
/**
|
||||
* If an SVG image's helper document has a pending notification for an
|
||||
* override on the root node's "preserveAspectRatio" attribute, then this
|
||||
* method will flush that notification so that the image can paint correctly.
|
||||
* (First, though, it sets the mIgnoreInvalidation flag so that we won't
|
||||
* notify the image's observers and trigger unwanted repaint-requests.)
|
||||
*/
|
||||
void FlushPreserveAspectRatioOverride();
|
||||
|
||||
/**
|
||||
* Returns a PRBool indicating whether the document has any SMIL animations.
|
||||
|
|
|
@ -539,6 +539,7 @@ VectorImage::Draw(gfxContext* aContext,
|
|||
mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize);
|
||||
mLastRenderedSize = aViewportSize;
|
||||
}
|
||||
mSVGDocumentWrapper->FlushPreserveAspectRatioOverride();
|
||||
|
||||
nsIntSize imageSize = mHaveRestrictedRegion ?
|
||||
mRestrictedRegion.Size() : aViewportSize;
|
||||
|
|