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
This commit is contained in:
Daniel Holbert 2010-12-19 16:45:29 -08:00
Родитель 50c74722b7
Коммит 2b17f89ee3
14 изменённых файлов: 204 добавлений и 5 удалений

Просмотреть файл

@ -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;