Bug 330498 - unify SVG effects (filter, clip, mask, opacity) logic. r+sr=roc
This commit is contained in:
Родитель
81b6cec562
Коммит
6d663c38d3
|
@ -67,7 +67,11 @@ nsSVGValue::NotifyObservers(SVGObserverNotifyFunction f,
|
|||
modificationType aModType)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
|
||||
// Since notification might cause the listeners to remove themselves
|
||||
// from the observer list (mod_die), walk backwards through the list
|
||||
// to catch everyone.
|
||||
for (PRInt32 i = count - 1; i >= 0; i--) {
|
||||
nsIWeakReference* wr = NS_STATIC_CAST(nsIWeakReference*,mObservers.ElementAt(i));
|
||||
nsCOMPtr<nsISVGValueObserver> observer = do_QueryReferent(wr);
|
||||
if (observer)
|
||||
|
|
|
@ -51,22 +51,14 @@ class nsIDOMSVGMatrix;
|
|||
struct nsRect;
|
||||
|
||||
#define NS_ISVGCHILDFRAME_IID \
|
||||
{ 0xe3280ee5, 0x0980, 0x45f4, { 0xb4, 0x84, 0xc4, 0x11, 0xbc, 0x36, 0xcd, 0xda } }
|
||||
{ 0x2a5b5908, 0x8b2a, 0x4991, { 0x97, 0x2e, 0xe4, 0x5f, 0x0a, 0xb2, 0x14, 0x9a } }
|
||||
|
||||
class nsISVGChildFrame : public nsISupports {
|
||||
public:
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGCHILDFRAME_IID)
|
||||
|
||||
// XXX Ideally we don't want to pass the dirtyRect along but extract
|
||||
// it from nsIRenderingContext where needed (only in foreign
|
||||
// objects) dirtyRectTwips is the unmodified region passed to the
|
||||
// outer svg frame's ::Paint. ignoreFilter tells the frame if it
|
||||
// should ignore any filter attribute set, as filters need to call
|
||||
// back to the frame to render source image(s).
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)=0;
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas)=0;
|
||||
|
||||
// Check if this frame or children contain the given point,
|
||||
// specified in device pixels relative to the origin of the outer
|
||||
|
@ -96,10 +88,6 @@ public:
|
|||
|
||||
// XXX move this function into interface nsISVGLocatableMetrics
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval)=0; // bbox in local coords
|
||||
|
||||
// Get the filtered invalidation area for this frame. Null return
|
||||
// if frame is not directly filtered.
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval)=0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGChildFrame, NS_ISVGCHILDFRAME_IID)
|
||||
|
|
|
@ -197,7 +197,7 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas,
|
|||
else {
|
||||
rv = canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP_MASK);
|
||||
|
||||
canvas->PushSurface(aClipSurface);
|
||||
canvas->PushSurface(aClipSurface, PR_TRUE);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -208,7 +208,7 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas,
|
|||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
SVGFrame->PaintSVG(canvas, dirty, PR_TRUE);
|
||||
SVGFrame->PaintSVG(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -194,9 +194,7 @@ nsSVGDefsFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGDefsFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGDefsFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
// defs don't paint
|
||||
|
||||
|
|
|
@ -94,9 +94,7 @@ public:
|
|||
#endif
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -106,10 +104,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_ERROR_FAILURE; }
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM) { return NS_ERROR_FAILURE; }
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
|
|
@ -269,8 +269,7 @@ nsSVGFilterFrame::FilterFailCleanup(nsISVGRendererCanvas *aCanvas,
|
|||
aTarget->SetOverrideCTM(nsnull);
|
||||
aTarget->SetMatrixPropagation(PR_TRUE);
|
||||
aTarget->NotifyCanvasTMChanged(PR_TRUE);
|
||||
nsRect dummyRect;
|
||||
aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE);
|
||||
aTarget->PaintSVG(aCanvas);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -308,8 +307,7 @@ nsSVGFilterFrame::FilterPaint(nsISVGRendererCanvas *aCanvas,
|
|||
if (unimplementedFilter)
|
||||
fprintf(stderr, "FilterFrame: unimplemented filter element\n");
|
||||
#endif
|
||||
nsRect dummyRect;
|
||||
aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE);
|
||||
aTarget->PaintSVG(aCanvas);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -401,9 +399,8 @@ nsSVGFilterFrame::FilterPaint(nsISVGRendererCanvas *aCanvas,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
aCanvas->PushSurface(surface);
|
||||
nsRect dummyRect;
|
||||
aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE);
|
||||
aCanvas->PushSurface(surface, PR_FALSE);
|
||||
aTarget->PaintSVG(aCanvas);
|
||||
aCanvas->PopSurface();
|
||||
|
||||
mPrimitiveUnits->GetAnimVal(&type);
|
||||
|
|
|
@ -60,12 +60,12 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsSVGFilterFrame.h"
|
||||
#include "nsSVGPoint.h"
|
||||
#include "nsSVGRect.h"
|
||||
#include "nsSVGMatrix.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsISVGRendererSurface.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
@ -85,19 +85,12 @@ NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent)
|
|||
}
|
||||
|
||||
nsSVGForeignObjectFrame::nsSVGForeignObjectFrame()
|
||||
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE), mFilter(nsnull)
|
||||
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE)
|
||||
{
|
||||
AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT |
|
||||
NS_FRAME_REFLOW_ROOT);
|
||||
}
|
||||
|
||||
nsSVGForeignObjectFrame::~nsSVGForeignObjectFrame()
|
||||
{
|
||||
if (mFilter) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsSVGForeignObjectFrame::Init()
|
||||
{
|
||||
nsCOMPtr<nsIDOMSVGForeignObjectElement> foreignObject = do_QueryInterface(mContent);
|
||||
|
@ -271,6 +264,13 @@ nsSVGForeignObjectFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGForeignObjectFrame::DidSetStyleContext()
|
||||
{
|
||||
nsSVGUtils::StyleEffects(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGValueObserver methods:
|
||||
|
||||
|
@ -278,20 +278,8 @@ NS_IMETHODIMP
|
|||
nsSVGForeignObjectFrame::WillModifySVGObservable(nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
nsSVGUtils::WillModifyEffects(this, observable, aModType);
|
||||
|
||||
// need to handle filters because we might be the topmost filtered frame and
|
||||
// the filter region could be changing.
|
||||
if (filter && mFilterRegion) {
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -301,29 +289,7 @@ nsSVGForeignObjectFrame::DidModifySVGObservable (nsISVGValue* observable,
|
|||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
Update();
|
||||
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
if (filter) {
|
||||
if (aModType == nsISVGValue::mod_die) {
|
||||
mFilter = nsnull;
|
||||
mFilterRegion = nsnull;
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mFilter)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
|
||||
if (region)
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
nsSVGUtils::DidModifyEffects(this, observable, aModType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -377,33 +343,14 @@ TransformRect(float* aX, float *aY, float* aWidth, float *aHeight,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mIsDirty) {
|
||||
nsCOMPtr<nsISVGRendererRegion> region = DoReflow();
|
||||
}
|
||||
|
||||
/* check for filter */
|
||||
|
||||
if (!ignoreFilter) {
|
||||
if (!mFilter) {
|
||||
nsCOMPtr<nsIURI> aURI = GetStyleSVGReset()->mFilter;
|
||||
if (aURI)
|
||||
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
|
||||
if (mFilter)
|
||||
NS_ADD_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
|
||||
if (mFilter) {
|
||||
if (!mFilterRegion)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
mFilter->FilterPaint(canvas, this);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsRect dirtyRect = nsRect(nsPoint(0, 0), GetSize());
|
||||
nsCOMPtr<nsIDOMSVGMatrix> tm = GetTMIncludingOffset();
|
||||
nsCOMPtr<nsIDOMSVGMatrix> inverse;
|
||||
|
|
|
@ -62,7 +62,6 @@ class nsSVGForeignObjectFrame : public nsSVGForeignObjectFrameBase,
|
|||
NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent);
|
||||
protected:
|
||||
nsSVGForeignObjectFrame();
|
||||
virtual ~nsSVGForeignObjectFrame();
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports interface:
|
||||
|
@ -96,6 +95,8 @@ public:
|
|||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
||||
NS_IMETHOD DidSetStyleContext();
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
*
|
||||
|
@ -124,9 +125,7 @@ public:
|
|||
// implementation inherited from nsSupportsWeakReference
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -136,11 +135,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = mFilterRegion;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
@ -171,9 +165,6 @@ protected:
|
|||
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
|
||||
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
|
||||
nsISVGFilterFrame *mFilter;
|
||||
|
||||
PRPackedBool mPropagateTransform;
|
||||
PRPackedBool mIsDirty;
|
||||
};
|
||||
|
|
|
@ -48,9 +48,7 @@
|
|||
#include "nsISVGRendererCanvas.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGFilterFrame.h"
|
||||
#include "nsISVGValueUtils.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsSVGGFrame)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
|
||||
|
@ -80,183 +78,30 @@ nsSVGGFrame::GetType() const
|
|||
return nsLayoutAtoms::svgGFrame;
|
||||
}
|
||||
|
||||
nsSVGGFrame::~nsSVGGFrame()
|
||||
{
|
||||
if (mFilter) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
|
||||
if (display->mOpacity == 0.0)
|
||||
return NS_OK;
|
||||
|
||||
nsIURI *aURI;
|
||||
|
||||
/* check for filter */
|
||||
|
||||
if (!ignoreFilter) {
|
||||
if (!mFilter) {
|
||||
aURI = GetStyleSVGReset()->mFilter;
|
||||
if (aURI)
|
||||
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
|
||||
if (mFilter)
|
||||
NS_ADD_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
|
||||
if (mFilter) {
|
||||
if (!mFilterRegion)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
mFilter->FilterPaint(canvas, this);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
|
||||
/* check for a clip path */
|
||||
|
||||
PRBool trivialClip = PR_TRUE;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
clip->IsTrivial(&trivialClip);
|
||||
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix,
|
||||
display->mOpacity)))
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame)
|
||||
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
|
||||
nsSVGUtils::PaintChildWithEffects(canvas, kid);
|
||||
}
|
||||
|
||||
if (maskedSurface)
|
||||
canvas->PopSurface();
|
||||
|
||||
if (clipMaskSurface) {
|
||||
if (!maskSurface && display->mOpacity == 1.0) {
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
canvas->PopSurface();
|
||||
maskedSurface = clipped;
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface)
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
|
||||
else if (display->mOpacity != 1.0)
|
||||
canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity);
|
||||
|
||||
if (clip && trivialClip)
|
||||
canvas->PopClip();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
|
||||
{
|
||||
*hit = nsnull;
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsIFrame* temp=nsnull;
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
|
||||
if (NS_SUCCEEDED(rv) && temp) {
|
||||
*hit = temp;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
}
|
||||
nsSVGUtils::HitTestChildren(this, x, y, hit);
|
||||
|
||||
if (*hit) {
|
||||
PRBool clipHit = PR_TRUE;;
|
||||
|
||||
nsIURI *aURI;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI)
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
clip->ClipHitTest(this, matrix, x, y, &clipHit);
|
||||
}
|
||||
|
||||
if (!clipHit)
|
||||
*hit = nsnull;
|
||||
}
|
||||
|
||||
return *hit ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
|
||||
|
@ -328,21 +173,7 @@ NS_IMETHODIMP
|
|||
nsSVGGFrame::WillModifySVGObservable(nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
// need to handle filters because we might be the topmost filtered frame and
|
||||
// the filter region could be changing.
|
||||
if (filter && mFilterRegion) {
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
|
||||
nsSVGUtils::WillModifyEffects(this, observable, aModType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -350,28 +181,13 @@ NS_IMETHODIMP
|
|||
nsSVGGFrame::DidModifySVGObservable(nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
if (filter) {
|
||||
if (aModType == nsISVGValue::mod_die) {
|
||||
mFilter = nsnull;
|
||||
mFilterRegion = nsnull;
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mFilter)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
|
||||
if (region)
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
|
||||
nsSVGUtils::DidModifyEffects(this, observable, aModType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGFrame::DidSetStyleContext()
|
||||
{
|
||||
nsSVGUtils::StyleEffects(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -52,9 +52,7 @@ class nsSVGGFrame : public nsSVGGFrameBase,
|
|||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsSVGGFrame() : mFilter(nsnull), mPropagateTransform(PR_TRUE) {}
|
||||
virtual ~nsSVGGFrame();
|
||||
|
||||
nsSVGGFrame() : mPropagateTransform(PR_TRUE) {}
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
|
@ -79,20 +77,16 @@ protected:
|
|||
friend nsIFrame*
|
||||
NS_NewSVGGFrame(nsIPresShell* aPresShell, nsIContent* aContent);
|
||||
|
||||
// nsIFrame interface:
|
||||
NS_IMETHOD DidSetStyleContext();
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = mFilterRegion;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
@ -105,9 +99,6 @@ protected:
|
|||
|
||||
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
|
||||
nsISVGFilterFrame *mFilter;
|
||||
|
||||
PRPackedBool mPropagateTransform;
|
||||
};
|
||||
|
||||
|
|
|
@ -186,9 +186,7 @@ nsSVGGenericContainerFrame::IsFrameOfType(PRUint32 aFlags) const
|
|||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGGenericContainer(%p)::Paint\n", this);
|
||||
|
@ -198,7 +196,7 @@ nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame)
|
||||
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
|
||||
SVGFrame->PaintSVG(canvas);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -207,26 +205,9 @@ nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
NS_IMETHODIMP
|
||||
nsSVGGenericContainerFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGGenericContainerFrame(%p)::GetFrameForPoint\n", this);
|
||||
#endif
|
||||
*hit = nsnull;
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsIFrame* temp=nsnull;
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
|
||||
if (NS_SUCCEEDED(rv) && temp) {
|
||||
*hit = temp;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
}
|
||||
nsSVGUtils::HitTestChildren(this, x, y, hit);
|
||||
|
||||
return *hit ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
|
||||
|
|
|
@ -100,9 +100,7 @@ public:
|
|||
#endif
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -112,10 +110,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_ERROR_FAILURE; }
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM) { return NS_ERROR_FAILURE; }
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
|
|
@ -132,9 +132,7 @@ public:
|
|||
nsISVGValue::modificationType aModType);
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -144,10 +142,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_OK; }
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM) { return NS_ERROR_FAILURE; }
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGGeometrySource interface:
|
||||
NS_DECL_NSISVGGEOMETRYSOURCE
|
||||
|
@ -482,9 +476,7 @@ nsSVGGlyphFrame::DidModifySVGObservable (nsISVGValue* observable,
|
|||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
//printf("nsSVGGlyphFrame(%p)::Paint\n", this);
|
||||
|
|
|
@ -135,9 +135,7 @@ public:
|
|||
|
||||
// nsISVGChildFrame interface:
|
||||
// Override PaintSVG (our frames don't directly render)
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter) {return NS_OK;}
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas) {return NS_OK;}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const
|
||||
|
|
|
@ -53,12 +53,9 @@
|
|||
#include "gfxIImageFrame.h"
|
||||
#include "nsIImage.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "nsSVGClipPathFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsISVGValueUtils.h"
|
||||
#include "nsSVGFilterFrame.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
|
@ -102,9 +99,7 @@ public:
|
|||
NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder);
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
|
||||
// nsISVGGeometrySource interface:
|
||||
NS_IMETHOD GetStrokePaintType(PRUint16 *aStrokePaintType);
|
||||
|
@ -286,33 +281,11 @@ NS_IMETHODIMP nsSVGImageFrame::ConstructPath(nsISVGRendererPathBuilder* pathBuil
|
|||
//----------------------------------------------------------------------
|
||||
// nsISVGChildFrame methods:
|
||||
NS_IMETHODIMP
|
||||
nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
if (!GetStyleVisibility()->IsVisible())
|
||||
return NS_OK;
|
||||
|
||||
nsIURI *aURI;
|
||||
|
||||
/* check for filter */
|
||||
if (!ignoreFilter) {
|
||||
if (!mFilter) {
|
||||
aURI = GetStyleSVGReset()->mFilter;
|
||||
if (aURI)
|
||||
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
|
||||
if (mFilter)
|
||||
NS_ADD_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
|
||||
if (mFilter) {
|
||||
if (!mFilterRegion)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
mFilter->FilterPaint(canvas, this);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSurfaceInvalid) {
|
||||
nsCOMPtr<imgIRequest> currentRequest;
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
||||
|
@ -336,71 +309,6 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
}
|
||||
}
|
||||
|
||||
canvas->PushClip();
|
||||
|
||||
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
|
||||
/* check for a clip path */
|
||||
|
||||
PRBool trivialClip = PR_TRUE;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
clip->IsTrivial(&trivialClip);
|
||||
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix)))
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
|
||||
if (mSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> ctm;
|
||||
GetCanvasTM(getter_AddRefs(ctm));
|
||||
|
@ -435,29 +343,6 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
mStyleContext->GetStyleDisplay()->mOpacity);
|
||||
}
|
||||
|
||||
if (maskedSurface)
|
||||
canvas->PopSurface();
|
||||
|
||||
if (clipMaskSurface) {
|
||||
if (!maskSurface) {
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
canvas->PopSurface();
|
||||
maskedSurface = clipped;
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface)
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
|
||||
|
||||
canvas->PopClip();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
#include "nsISVGValueUtils.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGClipPathFrame.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
#include "nsISVGRendererSurface.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
|
@ -75,7 +74,6 @@ class nsSVGInnerSVGFrame : public nsSVGInnerSVGFrameBase,
|
|||
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent);
|
||||
protected:
|
||||
nsSVGInnerSVGFrame();
|
||||
virtual ~nsSVGInnerSVGFrame();
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports interface:
|
||||
|
@ -97,6 +95,7 @@ public:
|
|||
nsIFrame* aParent,
|
||||
nsStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow);
|
||||
NS_IMETHOD DidSetStyleContext();
|
||||
|
||||
// We don't define an AttributeChanged method since changes to the
|
||||
// 'x', 'y', 'width' and 'height' attributes of our content object
|
||||
|
@ -118,9 +117,7 @@ public:
|
|||
#endif
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -130,11 +127,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = mFilterRegion;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
@ -162,9 +154,6 @@ protected:
|
|||
|
||||
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
|
||||
nsISVGFilterFrame *mFilter;
|
||||
|
||||
PRPackedBool mPropagateTransform;
|
||||
};
|
||||
|
||||
|
@ -177,24 +166,13 @@ NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent)
|
|||
return new (aPresShell) nsSVGInnerSVGFrame;
|
||||
}
|
||||
|
||||
nsSVGInnerSVGFrame::nsSVGInnerSVGFrame() : mFilter(nsnull),
|
||||
mPropagateTransform(PR_TRUE)
|
||||
nsSVGInnerSVGFrame::nsSVGInnerSVGFrame() : mPropagateTransform(PR_TRUE)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGInnerSVGFrame CTOR\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
nsSVGInnerSVGFrame::~nsSVGInnerSVGFrame()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("~nsSVGInnerSVGFrame\n");
|
||||
#endif
|
||||
if (mFilter) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsSVGInnerSVGFrame::Init()
|
||||
{
|
||||
NS_ASSERTION(mParent, "no parent");
|
||||
|
@ -338,37 +316,12 @@ nsSVGInnerSVGFrame::IsFrameOfType(PRUint32 aFlags) const
|
|||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGInnerSVG(%p)::Paint\n", this);
|
||||
#endif
|
||||
|
||||
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
|
||||
|
||||
nsIURI *aURI;
|
||||
|
||||
/* check for filter */
|
||||
|
||||
if (!ignoreFilter) {
|
||||
if (!mFilter) {
|
||||
aURI = GetStyleSVGReset()->mFilter;
|
||||
if (aURI)
|
||||
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
|
||||
if (mFilter)
|
||||
NS_ADD_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
|
||||
if (mFilter) {
|
||||
if (!mFilterRegion)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
mFilter->FilterPaint(canvas, this);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
canvas->PushClip();
|
||||
|
||||
if (GetStyleDisplay()->IsScrollableOverflow()) {
|
||||
|
@ -400,97 +353,11 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
canvas->SetClipRect(clipTransform, x, y, width, height);
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
|
||||
/* check for a clip path */
|
||||
|
||||
PRBool trivialClip = PR_TRUE;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
clip->IsTrivial(&trivialClip);
|
||||
|
||||
if (!trivialClip) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix,
|
||||
display->mOpacity)))
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame)
|
||||
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
|
||||
nsSVGUtils::PaintChildWithEffects(canvas, kid);
|
||||
}
|
||||
|
||||
if (maskedSurface)
|
||||
canvas->PopSurface();
|
||||
|
||||
if (clipMaskSurface) {
|
||||
if (!maskSurface && display->mOpacity == 1.0) {
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
canvas->PopSurface();
|
||||
maskedSurface = clipped;
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface)
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
|
||||
else if (display->mOpacity != 1.0)
|
||||
canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity);
|
||||
|
||||
canvas->PopClip();
|
||||
|
||||
return NS_OK;
|
||||
|
@ -499,26 +366,9 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
NS_IMETHODIMP
|
||||
nsSVGInnerSVGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGInnerSVGFrame(%p)::GetFrameForPoint\n", this);
|
||||
#endif
|
||||
*hit = nsnull;
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsIFrame* temp=nsnull;
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
|
||||
if (NS_SUCCEEDED(rv) && temp) {
|
||||
*hit = temp;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
}
|
||||
nsSVGUtils::HitTestChildren(this, x, y, hit);
|
||||
|
||||
return *hit ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
|
||||
|
@ -791,21 +641,7 @@ NS_IMETHODIMP
|
|||
nsSVGInnerSVGFrame::WillModifySVGObservable(nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
// need to handle filters because we might be the topmost filtered frame and
|
||||
// the filter region could be changing.
|
||||
if (filter && mFilterRegion) {
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
|
||||
nsSVGUtils::WillModifyEffects(this, observable, aModType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -816,27 +652,18 @@ nsSVGInnerSVGFrame::DidModifySVGObservable (nsISVGValue* observable,
|
|||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
if (filter) {
|
||||
if (aModType == nsISVGValue::mod_die) {
|
||||
mFilter = nsnull;
|
||||
mFilterRegion = nsnull;
|
||||
}
|
||||
nsSVGUtils::DidModifyEffects(this, observable, aModType);
|
||||
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mFilter)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
|
||||
if (region)
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
} else {
|
||||
if (!filter) {
|
||||
NotifyViewportChange();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGInnerSVGFrame::DidSetStyleContext()
|
||||
{
|
||||
nsSVGUtils::StyleEffects(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -377,14 +377,13 @@ nsSVGMarkerFrame::PaintMark(nsISVGRendererCanvas *aCanvas,
|
|||
}
|
||||
}
|
||||
|
||||
nsRect dirtyRectTwips;
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
SVGFrame->NotifyCanvasTMChanged(PR_TRUE);
|
||||
SVGFrame->PaintSVG(aCanvas, dirtyRectTwips, PR_FALSE);
|
||||
nsSVGUtils::PaintChildWithEffects(aCanvas, kid);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ nsSVGMaskFrame::MaskPaint(nsISVGRendererCanvas* aCanvas,
|
|||
{
|
||||
nsRect dirty;
|
||||
|
||||
if (NS_FAILED(aCanvas->PushSurface(aSurface)))
|
||||
if (NS_FAILED(aCanvas->PushSurface(aSurface, PR_TRUE)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
{
|
||||
|
@ -300,11 +300,7 @@ nsSVGMaskFrame::MaskPaint(nsISVGRendererCanvas* aCanvas,
|
|||
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
SVGFrame->PaintSVG(aCanvas, dirty, PR_TRUE);
|
||||
}
|
||||
nsSVGUtils::PaintChildWithEffects(aCanvas, kid);
|
||||
}
|
||||
|
||||
aCanvas->PopSurface();
|
||||
|
|
|
@ -635,23 +635,10 @@ nsSVGOuterSVGFrame::GetFrameForPoint(const nsPoint& aPoint)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsIFrame* frame = this;
|
||||
nsIFrame* hit = nsnull;
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &hit);
|
||||
if (NS_SUCCEEDED(rv) && hit) {
|
||||
frame = hit;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIFrame* hit;
|
||||
nsSVGUtils::HitTestChildren(this, x, y, &hit);
|
||||
|
||||
return frame;
|
||||
return hit;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -737,10 +724,7 @@ nsSVGOuterSVGFrame::Paint(nsIRenderingContext& aRenderingContext,
|
|||
// paint children:
|
||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame)
|
||||
SVGFrame->PaintSVG(canvas, dirtyRect, PR_FALSE);
|
||||
nsSVGUtils::PaintChildWithEffects(canvas, kid);
|
||||
}
|
||||
|
||||
canvas->Flush();
|
||||
|
|
|
@ -70,9 +70,7 @@
|
|||
// nsSVGPathGeometryFrame
|
||||
|
||||
nsSVGPathGeometryFrame::nsSVGPathGeometryFrame()
|
||||
: mFilter(nsnull), mUpdateFlags(0), mPropagateTransform(PR_TRUE),
|
||||
mFillGradient(nsnull), mStrokeGradient(nsnull),
|
||||
mFillPattern(nsnull), mStrokePattern(nsnull)
|
||||
: mUpdateFlags(0), mPropagateTransform(PR_TRUE)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGPathGeometryFrame %p CTOR\n", this);
|
||||
|
@ -91,9 +89,6 @@ nsSVGPathGeometryFrame::~nsSVGPathGeometryFrame()
|
|||
if (mStrokeGradient) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mStrokeGradient);
|
||||
}
|
||||
if (mFilter) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
if (mFillPattern) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFillPattern);
|
||||
}
|
||||
|
@ -162,10 +157,6 @@ nsSVGPathGeometryFrame::DidSetStyleContext()
|
|||
NS_REMOVE_SVGVALUE_OBSERVER(mStrokeGradient);
|
||||
mStrokeGradient = nsnull;
|
||||
}
|
||||
if (mFilter) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
|
||||
mFilter = nsnull;
|
||||
}
|
||||
if (mFillPattern) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFillPattern);
|
||||
mFillPattern = nsnull;
|
||||
|
@ -174,6 +165,7 @@ nsSVGPathGeometryFrame::DidSetStyleContext()
|
|||
NS_REMOVE_SVGVALUE_OBSERVER(mStrokePattern);
|
||||
mStrokePattern = nsnull;
|
||||
}
|
||||
nsSVGUtils::StyleEffects(this);
|
||||
|
||||
// XXX: we'd like to use the style_hint mechanism and the
|
||||
// ContentStateChanged/AttributeChanged functions for style changes
|
||||
|
@ -225,97 +217,11 @@ nsSVGPathGeometryFrame::GetMarkerFrames(nsISVGMarkerFrame **markerStart,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
if (!GetStyleVisibility()->IsVisible())
|
||||
return NS_OK;
|
||||
|
||||
nsIURI *aURI;
|
||||
|
||||
/* check for filter */
|
||||
|
||||
if (!ignoreFilter) {
|
||||
if (!mFilter) {
|
||||
aURI = GetStyleSVGReset()->mFilter;
|
||||
if (aURI)
|
||||
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
|
||||
if (mFilter)
|
||||
NS_ADD_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
|
||||
if (mFilter) {
|
||||
if (!mFilterRegion)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
mFilter->FilterPaint(canvas, this);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
|
||||
/* check for a clip path */
|
||||
|
||||
PRBool trivialClip = PR_TRUE;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
clip->IsTrivial(&trivialClip);
|
||||
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix)))
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
|
||||
/* render */
|
||||
GetGeometry()->Render(canvas);
|
||||
|
||||
|
@ -351,30 +257,6 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
}
|
||||
}
|
||||
|
||||
if (maskedSurface)
|
||||
canvas->PopSurface();
|
||||
|
||||
if (clipMaskSurface) {
|
||||
if (!maskSurface) {
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
canvas->PopSurface();
|
||||
maskedSurface = clipped;
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface)
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
|
||||
|
||||
if (clip && trivialClip)
|
||||
canvas->PopClip();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -390,24 +272,8 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
|
|||
PRBool isHit;
|
||||
GetGeometry()->ContainsPoint(x, y, &isHit);
|
||||
|
||||
if (isHit) {
|
||||
PRBool clipHit = PR_TRUE;;
|
||||
|
||||
nsIURI *aURI;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI)
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
clip->ClipHitTest(this, matrix, x, y, &clipHit);
|
||||
}
|
||||
|
||||
if (clipHit)
|
||||
if (isHit && nsSVGUtils::HitTestClip(this, x, y))
|
||||
*hit = this;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -536,20 +402,7 @@ NS_IMETHODIMP
|
|||
nsSVGPathGeometryFrame::WillModifySVGObservable(nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
// need to handle filters because we might be the topmost filtered frame and
|
||||
// the filter region could be changing.
|
||||
if (filter && mFilterRegion) {
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
nsSVGUtils::WillModifyEffects(this, observable, aModType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -566,6 +419,8 @@ nsSVGPathGeometryFrame::DidModifySVGObservable (nsISVGValue* observable,
|
|||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
nsSVGUtils::DidModifyEffects(this, observable, aModType);
|
||||
|
||||
if (gradient) {
|
||||
// Yes, we need to handle this differently
|
||||
nsCOMPtr<nsISVGGradient>fill = do_QueryInterface(mFillGradient);
|
||||
|
@ -582,10 +437,6 @@ nsSVGPathGeometryFrame::DidModifySVGObservable (nsISVGValue* observable,
|
|||
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_STROKE_PAINT);
|
||||
}
|
||||
} else if (filter) {
|
||||
if (aModType == nsISVGValue::mod_die) {
|
||||
mFilter = nsnull;
|
||||
mFilterRegion = nsnull;
|
||||
}
|
||||
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_STROKE_PAINT |
|
||||
nsISVGGeometrySource::UPDATEMASK_FILL_PAINT);
|
||||
} else if (pval) {
|
||||
|
@ -674,8 +525,7 @@ nsSVGPathGeometryFrame::GetCanvasTM(nsIDOMSVGMatrix * *aCTM)
|
|||
NS_IMETHODIMP
|
||||
nsSVGPathGeometryFrame::GetStrokeOpacity(float *aStrokeOpacity)
|
||||
{
|
||||
*aStrokeOpacity =
|
||||
GetStyleSVG()->mStrokeOpacity * GetStyleDisplay()->mOpacity;
|
||||
*aStrokeOpacity = GetStyleSVG()->mStrokeOpacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -766,8 +616,7 @@ nsSVGPathGeometryFrame::GetStrokeMiterlimit(float *aStrokeMiterlimit)
|
|||
NS_IMETHODIMP
|
||||
nsSVGPathGeometryFrame::GetFillOpacity(float *aFillOpacity)
|
||||
{
|
||||
*aFillOpacity =
|
||||
GetStyleSVG()->mFillOpacity * GetStyleDisplay()->mOpacity;
|
||||
*aFillOpacity = GetStyleSVG()->mFillOpacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,9 +111,7 @@ protected:
|
|||
nsISVGValue::modificationType aModType);
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -123,11 +121,6 @@ protected:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = mFilterRegion;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISupportsWeakReference
|
||||
// implementation inherited from nsSupportsWeakReference
|
||||
|
@ -146,9 +139,7 @@ protected:
|
|||
void UpdateGraphic(PRUint32 flags, PRBool suppressInvalidation = PR_FALSE);
|
||||
nsISVGRendererPathGeometry *GetGeometry();
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
|
||||
nsCOMPtr<nsISVGRendererRegion> mMarkerRegion;
|
||||
nsISVGFilterFrame *mFilter;
|
||||
|
||||
private:
|
||||
void GetMarkerFrames(nsISVGMarkerFrame **markerStart,
|
||||
|
|
|
@ -488,7 +488,7 @@ nsSVGPatternFrame::PaintPattern(nsISVGRendererCanvas* canvas,
|
|||
getter_AddRefs(patternSurface));
|
||||
|
||||
// Push the surface
|
||||
if (NS_FAILED(canvas->PushSurface(patternSurface)))
|
||||
if (NS_FAILED(canvas->PushSurface(patternSurface, PR_FALSE)))
|
||||
return NS_ERROR_FAILURE; //?
|
||||
|
||||
if (NS_FAILED(GetPatternMatrix(patternMatrix, bbox, viewRect)))
|
||||
|
@ -520,11 +520,7 @@ nsSVGPatternFrame::PaintPattern(nsISVGRendererCanvas* canvas,
|
|||
nsRect dummyRect;
|
||||
for (nsIFrame* kid = firstKid; kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame=nsnull;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
SVGFrame->PaintSVG(canvas, dummyRect, PR_FALSE);
|
||||
}
|
||||
nsSVGUtils::PaintChildWithEffects(canvas, kid);
|
||||
}
|
||||
mSource = nsnull;
|
||||
|
||||
|
|
|
@ -278,9 +278,7 @@ nsSVGTSpanFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
|
|||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGTSpanFrame(%p)::Paint\n", this);
|
||||
|
@ -291,7 +289,7 @@ nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
nsISVGChildFrame* SVGFrame=0;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame)
|
||||
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
|
||||
SVGFrame->PaintSVG(canvas);
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
|
||||
|
@ -301,27 +299,9 @@ nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
NS_IMETHODIMP
|
||||
nsSVGTSpanFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGTSpanFrame(%p)::GetFrameForPoint\n", this);
|
||||
#endif
|
||||
*hit = nsnull;
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
while (kid) {
|
||||
nsISVGChildFrame* SVGFrame=0;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsIFrame* temp=nsnull;
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
|
||||
if (NS_SUCCEEDED(rv) && temp) {
|
||||
*hit = temp;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
nsSVGUtils::HitTestChildren(this, x, y, hit);
|
||||
|
||||
return *hit ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
|
||||
|
|
|
@ -127,9 +127,7 @@ public:
|
|||
// implementation inherited from nsSupportsWeakReference
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -139,10 +137,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
|
|
@ -66,10 +66,8 @@
|
|||
#include "nsLayoutAtoms.h"
|
||||
#include "nsISVGPathFlatten.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGFilterFrame.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
#include "nsSVGClipPathFrame.h"
|
||||
#include "nsISVGRendererSurface.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -89,7 +87,6 @@ class nsSVGTextFrame : public nsSVGTextFrameBase,
|
|||
NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent);
|
||||
protected:
|
||||
nsSVGTextFrame();
|
||||
virtual ~nsSVGTextFrame();
|
||||
|
||||
// nsISupports interface:
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
@ -148,9 +145,7 @@ public:
|
|||
// implementation inherited from nsSupportsWeakReference
|
||||
|
||||
// nsISVGChildFrame interface:
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter);
|
||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
|
||||
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
|
||||
NS_IMETHOD InitialUpdate();
|
||||
|
@ -160,11 +155,6 @@ public:
|
|||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
|
||||
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
|
||||
*_retval = mFilterRegion;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||
|
@ -205,9 +195,6 @@ protected:
|
|||
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
|
||||
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
|
||||
nsISVGFilterFrame *mFilter;
|
||||
|
||||
PRPackedBool mFragmentTreeDirty;
|
||||
PRPackedBool mPositioningDirty;
|
||||
|
||||
|
@ -235,17 +222,10 @@ NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent)
|
|||
nsSVGTextFrame::nsSVGTextFrame()
|
||||
: mFragmentTreeState(suspended), mMetricsState(suspended),
|
||||
mFragmentTreeDirty(PR_FALSE), mPositioningDirty(PR_FALSE),
|
||||
mPropagateTransform(PR_TRUE), mFilter(nsnull)
|
||||
mPropagateTransform(PR_TRUE)
|
||||
{
|
||||
}
|
||||
|
||||
nsSVGTextFrame::~nsSVGTextFrame()
|
||||
{
|
||||
if (mFilter) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISupports methods
|
||||
|
||||
|
@ -304,6 +284,7 @@ nsSVGTextFrame::DidSetStyleContext()
|
|||
#ifdef DEBUG
|
||||
printf("** nsSVGTextFrame::DidSetStyleContext\n");
|
||||
#endif
|
||||
nsSVGUtils::StyleEffects(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -402,20 +383,8 @@ NS_IMETHODIMP
|
|||
nsSVGTextFrame::WillModifySVGObservable(nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
nsSVGUtils::WillModifyEffects(this, observable, aModType);
|
||||
|
||||
// need to handle filters because we might be the topmost filtered frame and
|
||||
// the filter region could be changing.
|
||||
if (filter && mFilterRegion) {
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -424,28 +393,7 @@ NS_IMETHODIMP
|
|||
nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
if (filter) {
|
||||
if (aModType == nsISVGValue::mod_die) {
|
||||
mFilter = nsnull;
|
||||
mFilterRegion = nsnull;
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
if (!outerSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mFilter)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
|
||||
|
||||
if (region)
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
nsSVGUtils::DidModifyEffects(this, observable, aModType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -552,9 +500,7 @@ nsSVGTextFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
|
|||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGTextFrame(%p)::Paint\n", this);
|
||||
|
@ -564,151 +510,24 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
|||
if (display->mOpacity == 0.0)
|
||||
return NS_OK;
|
||||
|
||||
nsIURI *aURI;
|
||||
|
||||
/* check for filter */
|
||||
|
||||
if (!ignoreFilter) {
|
||||
if (!mFilter) {
|
||||
aURI = GetStyleSVGReset()->mFilter;
|
||||
if (aURI)
|
||||
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
|
||||
if (mFilter)
|
||||
NS_ADD_SVGVALUE_OBSERVER(mFilter);
|
||||
}
|
||||
|
||||
if (mFilter) {
|
||||
if (!mFilterRegion)
|
||||
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
|
||||
mFilter->FilterPaint(canvas, this);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
|
||||
|
||||
/* check for a clip path */
|
||||
|
||||
PRBool trivialClip = PR_TRUE;
|
||||
nsISVGClipPathFrame *clip = NULL;
|
||||
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
clip->IsTrivial(&trivialClip);
|
||||
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix,
|
||||
display->mOpacity)))
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
maskSurface = nsnull;
|
||||
}
|
||||
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
while (kid) {
|
||||
nsISVGChildFrame* SVGFrame=0;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame)
|
||||
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
|
||||
SVGFrame->PaintSVG(canvas);
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
|
||||
if (maskedSurface)
|
||||
canvas->PopSurface();
|
||||
|
||||
if (clipMaskSurface) {
|
||||
if (!maskSurface && display->mOpacity == 1.0) {
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
canvas->PopSurface();
|
||||
maskedSurface = clipped;
|
||||
}
|
||||
}
|
||||
|
||||
if (maskSurface)
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
|
||||
else if (display->mOpacity != 1.0)
|
||||
canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity);
|
||||
|
||||
if (clip && trivialClip)
|
||||
canvas->PopClip();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGTextFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGTextFrame(%p)::GetFrameForPoint\n", this);
|
||||
#endif
|
||||
*hit = nsnull;
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
while (kid) {
|
||||
nsISVGChildFrame* SVGFrame=0;
|
||||
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsIFrame* temp=nsnull;
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
|
||||
if (NS_SUCCEEDED(rv) && temp) {
|
||||
*hit = temp;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
nsSVGUtils::HitTestChildren(this, x, y, hit);
|
||||
|
||||
return *hit ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
|
||||
|
|
|
@ -70,6 +70,16 @@
|
|||
#include "nsIDOMSVGAnimPresAspRatio.h"
|
||||
#include "nsIDOMSVGPresAspectRatio.h"
|
||||
#include "nsSVGMatrix.h"
|
||||
#include "nsSVGFilterFrame.h"
|
||||
#include "nsSVGClipPathFrame.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
#include "nsISVGRendererSurface.h"
|
||||
#include "nsISVGContainerFrame.h"
|
||||
|
||||
struct nsSVGFilterProperty {
|
||||
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
|
||||
nsISVGFilterFrame *mFilter;
|
||||
};
|
||||
|
||||
static PRBool gSVGEnabled;
|
||||
static PRBool gSVGRendererAvailable = PR_FALSE;
|
||||
|
@ -477,15 +487,19 @@ void
|
|||
nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame,
|
||||
nsISVGRendererRegion **aRegion)
|
||||
{
|
||||
nsCOMPtr<nsISVGRendererRegion> region, tmp;
|
||||
*aRegion = nsnull;
|
||||
nsISVGRendererRegion *region = nsnull;
|
||||
|
||||
while (aFrame != nsnull) {
|
||||
nsISVGChildFrame *svg;
|
||||
CallQueryInterface(aFrame, &svg);
|
||||
if (svg)
|
||||
svg->GetFilterRegion(getter_AddRefs(tmp));
|
||||
if (tmp)
|
||||
region = tmp;
|
||||
while (aFrame) {
|
||||
if (aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)
|
||||
break;
|
||||
|
||||
if (aFrame->GetStateBits() & NS_STATE_SVG_FILTERED) {
|
||||
nsSVGFilterProperty *property;
|
||||
property = NS_STATIC_CAST(nsSVGFilterProperty *,
|
||||
aFrame->GetProperty(nsGkAtoms::filter));
|
||||
region = property->mFilterRegion;
|
||||
}
|
||||
aFrame = aFrame->GetParent();
|
||||
}
|
||||
|
||||
|
@ -734,3 +748,387 @@ nsSVGUtils::GetViewBoxTransform(float aViewportWidth, float aViewportHeight,
|
|||
NS_NewSVGMatrix(&retval, a, 0.0f, 0.0f, d, e, f);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// This is ugly and roc will want to kill me...
|
||||
|
||||
already_AddRefed<nsIDOMSVGMatrix>
|
||||
nsSVGUtils::GetCanvasTM(nsIFrame *aFrame)
|
||||
{
|
||||
nsISVGContainerFrame *containerFrame = nsnull;
|
||||
CallQueryInterface(aFrame, &containerFrame);
|
||||
if (containerFrame) {
|
||||
return containerFrame->GetCanvasTM();
|
||||
}
|
||||
|
||||
nsISVGGeometrySource *geometrySource = nsnull;
|
||||
CallQueryInterface(aFrame, &geometrySource);
|
||||
if (geometrySource) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
nsIDOMSVGMatrix *retval;
|
||||
geometrySource->GetCanvasTM(getter_AddRefs(matrix));
|
||||
retval = matrix.get();
|
||||
NS_IF_ADDREF(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// Effect helper functions
|
||||
|
||||
static void
|
||||
AddObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
{
|
||||
nsISVGValueObserver *observer = nsnull;
|
||||
nsISVGValue *v = nsnull;
|
||||
CallQueryInterface(aObserver, &observer);
|
||||
CallQueryInterface(aTarget, &v);
|
||||
if (observer && v)
|
||||
v->AddObserver(observer);
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
{
|
||||
nsISVGValueObserver *observer = nsnull;
|
||||
nsISVGValue *v = nsnull;
|
||||
CallQueryInterface(aObserver, &observer);
|
||||
CallQueryInterface(aTarget, &v);
|
||||
if (observer && v)
|
||||
v->RemoveObserver(observer);
|
||||
}
|
||||
|
||||
static void
|
||||
FilterPropertyDtor(void *aObject, nsIAtom *aPropertyName,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
nsSVGFilterProperty *property = (nsSVGFilterProperty *)aPropertyValue;
|
||||
RemoveObserver((nsIFrame *)aObject, property->mFilter);
|
||||
delete property;
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateFilterRegion(nsIFrame *aFrame)
|
||||
{
|
||||
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(aFrame);
|
||||
if (outerSVGFrame) {
|
||||
nsCOMPtr<nsISVGRendererRegion> region;
|
||||
nsSVGUtils::FindFilterInvalidation(aFrame, getter_AddRefs(region));
|
||||
if (region)
|
||||
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AddEffectProperties(nsIFrame *aFrame)
|
||||
{
|
||||
const nsStyleSVGReset *style = aFrame->GetStyleSVGReset();
|
||||
|
||||
if (style->mFilter && !(aFrame->GetStateBits() & NS_STATE_SVG_FILTERED)) {
|
||||
nsISVGFilterFrame *filter;
|
||||
NS_GetSVGFilterFrame(&filter, style->mFilter, aFrame->GetContent());
|
||||
if (filter) {
|
||||
AddObserver(aFrame, filter);
|
||||
nsSVGFilterProperty *property = new nsSVGFilterProperty;
|
||||
property->mFilter = filter;
|
||||
filter->GetInvalidationRegion(aFrame, getter_AddRefs(property->mFilterRegion));
|
||||
aFrame->SetProperty(nsGkAtoms::filter, property, FilterPropertyDtor);
|
||||
aFrame->AddStateBits(NS_STATE_SVG_FILTERED);
|
||||
}
|
||||
}
|
||||
|
||||
if (style->mClipPath && !(aFrame->GetStateBits() & NS_STATE_SVG_CLIPPED_MASK)) {
|
||||
nsISVGClipPathFrame *clip;
|
||||
NS_GetSVGClipPathFrame(&clip, style->mClipPath, aFrame->GetContent());
|
||||
if (clip) {
|
||||
aFrame->SetProperty(nsGkAtoms::clipPath, clip);
|
||||
|
||||
PRBool trivialClip;
|
||||
clip->IsTrivial(&trivialClip);
|
||||
if (trivialClip)
|
||||
aFrame->AddStateBits(NS_STATE_SVG_CLIPPED_TRIVIAL);
|
||||
else
|
||||
aFrame->AddStateBits(NS_STATE_SVG_CLIPPED_COMPLEX);
|
||||
}
|
||||
}
|
||||
|
||||
if (style->mMask && !(aFrame->GetStateBits() & NS_STATE_SVG_MASKED)) {
|
||||
nsISVGMaskFrame *mask;
|
||||
NS_GetSVGMaskFrame(&mask, style->mMask, aFrame->GetContent());
|
||||
if (mask) {
|
||||
aFrame->SetProperty(nsGkAtoms::mask, mask);
|
||||
aFrame->AddStateBits(NS_STATE_SVG_MASKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<nsISVGRendererSurface>
|
||||
GetComplexClipSurface(nsISVGRendererCanvas *aCanvas, nsIFrame *aFrame)
|
||||
{
|
||||
nsISVGRendererSurface *surface = nsnull;
|
||||
|
||||
if (aFrame->GetStateBits() & NS_STATE_SVG_CLIPPED_COMPLEX) {
|
||||
nsISVGChildFrame *svgChildFrame;
|
||||
CallQueryInterface(aFrame, &svgChildFrame);
|
||||
|
||||
nsISVGClipPathFrame *clip;
|
||||
clip = NS_STATIC_CAST(nsISVGClipPathFrame *,
|
||||
aFrame->GetProperty(nsGkAtoms::clipPath));
|
||||
|
||||
nsSVGUtils::GetSurface(nsSVGUtils::GetOuterSVGFrame(aFrame),
|
||||
aCanvas, &surface);
|
||||
if (surface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = nsSVGUtils::GetCanvasTM(aFrame);
|
||||
if (NS_FAILED(clip->ClipPaint(aCanvas, surface, svgChildFrame,
|
||||
matrix))) {
|
||||
delete surface;
|
||||
surface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static already_AddRefed<nsISVGRendererSurface>
|
||||
GetMaskSurface(nsISVGRendererCanvas *aCanvas, nsIFrame *aFrame, float opacity)
|
||||
{
|
||||
nsISVGRendererSurface *surface = nsnull;
|
||||
|
||||
if (aFrame->GetStateBits() & NS_STATE_SVG_MASKED) {
|
||||
nsISVGChildFrame *svgChildFrame;
|
||||
CallQueryInterface(aFrame, &svgChildFrame);
|
||||
|
||||
nsISVGMaskFrame *mask;
|
||||
mask = NS_STATIC_CAST(nsISVGMaskFrame *,
|
||||
aFrame->GetProperty(nsGkAtoms::mask));
|
||||
|
||||
nsSVGUtils::GetSurface(nsSVGUtils::GetOuterSVGFrame(aFrame),
|
||||
aCanvas, &surface);
|
||||
if (surface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = nsSVGUtils::GetCanvasTM(aFrame);
|
||||
if (NS_FAILED(mask->MaskPaint(aCanvas, surface, svgChildFrame,
|
||||
matrix, opacity))) {
|
||||
delete surface;
|
||||
surface = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************
|
||||
|
||||
void
|
||||
nsSVGUtils::PaintChildWithEffects(nsISVGRendererCanvas *aCanvas,
|
||||
nsIFrame *aFrame)
|
||||
{
|
||||
nsISVGChildFrame *svgChildFrame;
|
||||
CallQueryInterface(aFrame, &svgChildFrame);
|
||||
|
||||
if (!svgChildFrame)
|
||||
return;
|
||||
|
||||
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(aFrame);
|
||||
float opacity = aFrame->GetStyleDisplay()->mOpacity;
|
||||
|
||||
/* Properties are added lazily and may have been removed by a restyle,
|
||||
so make sure all applicable ones are set again. */
|
||||
|
||||
AddEffectProperties(aFrame);
|
||||
nsFrameState state = aFrame->GetStateBits();
|
||||
|
||||
/* SVG defines the following rendering model:
|
||||
*
|
||||
* 1. Render geometry
|
||||
* 2. Apply filter
|
||||
* 3. Apply clipping, masking, group opacity
|
||||
*
|
||||
* We follow this, but perform a couple optimizations:
|
||||
*
|
||||
* + Use cairo's clipPath when representable natively (single object
|
||||
* clip region).
|
||||
*
|
||||
* + Merge opacity and masking if both used together.
|
||||
*/
|
||||
|
||||
nsCOMPtr<nsISVGRendererSurface> offscreenSurface;
|
||||
|
||||
/* Check if we need to do additional operations on this child's
|
||||
* rendering, which necessitates rendering into another surface. */
|
||||
if (opacity != 1.0 ||
|
||||
state & (NS_STATE_SVG_CLIPPED_COMPLEX | NS_STATE_SVG_MASKED)) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame,
|
||||
aCanvas, getter_AddRefs(offscreenSurface));
|
||||
if (offscreenSurface) {
|
||||
aCanvas->PushSurface(offscreenSurface, PR_TRUE);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this frame has only a trivial clipPath, set up cairo's clipping now so
|
||||
* we can just do normal painting and get it clipped appropriately.
|
||||
*/
|
||||
if (state & NS_STATE_SVG_CLIPPED_TRIVIAL) {
|
||||
nsISVGClipPathFrame *clip;
|
||||
clip = NS_STATIC_CAST(nsISVGClipPathFrame *,
|
||||
aFrame->GetProperty(nsGkAtoms::clipPath));
|
||||
|
||||
aCanvas->PushClip();
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
|
||||
clip->ClipPaint(aCanvas, nsnull, svgChildFrame, matrix);
|
||||
}
|
||||
|
||||
/* Paint the child */
|
||||
if (state & NS_STATE_SVG_FILTERED) {
|
||||
nsSVGFilterProperty *property;
|
||||
property = NS_STATIC_CAST(nsSVGFilterProperty *,
|
||||
aFrame->GetProperty(nsGkAtoms::filter));
|
||||
property->mFilter->FilterPaint(aCanvas, svgChildFrame);
|
||||
} else {
|
||||
svgChildFrame->PaintSVG(aCanvas);
|
||||
}
|
||||
|
||||
if (state & NS_STATE_SVG_CLIPPED_TRIVIAL) {
|
||||
aCanvas->PopClip();
|
||||
}
|
||||
|
||||
/* No more effects, we're done. */
|
||||
if (!offscreenSurface)
|
||||
return;
|
||||
|
||||
aCanvas->PopSurface();
|
||||
|
||||
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface, maskSurface;
|
||||
|
||||
clipMaskSurface = GetComplexClipSurface(aCanvas, aFrame);
|
||||
maskSurface = GetMaskSurface(aCanvas, aFrame, opacity);
|
||||
|
||||
nsCOMPtr<nsISVGRendererSurface> clippedSurface;
|
||||
|
||||
if (clipMaskSurface) {
|
||||
// Still more set after clipping, so clip to another surface
|
||||
if (maskSurface || opacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, aCanvas,
|
||||
getter_AddRefs(clippedSurface));
|
||||
|
||||
if (clippedSurface) {
|
||||
aCanvas->PushSurface(clippedSurface, PR_TRUE);
|
||||
aCanvas->CompositeSurfaceWithMask(offscreenSurface, clipMaskSurface);
|
||||
aCanvas->PopSurface();
|
||||
}
|
||||
} else {
|
||||
aCanvas->CompositeSurfaceWithMask(offscreenSurface, clipMaskSurface);
|
||||
}
|
||||
}
|
||||
|
||||
// No clipping or out of memory creating clip dest surface (skip clipping)
|
||||
if (!clippedSurface) {
|
||||
clippedSurface = offscreenSurface;
|
||||
}
|
||||
|
||||
if (maskSurface)
|
||||
aCanvas->CompositeSurfaceWithMask(clippedSurface, maskSurface);
|
||||
else if (opacity != 1.0)
|
||||
aCanvas->CompositeSurface(clippedSurface, opacity);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGUtils::StyleEffects(nsIFrame *aFrame)
|
||||
{
|
||||
nsFrameState state = aFrame->GetStateBits();
|
||||
|
||||
/* clear out all effects */
|
||||
|
||||
if (state & NS_STATE_SVG_CLIPPED_MASK) {
|
||||
aFrame->DeleteProperty(nsGkAtoms::clipPath);
|
||||
}
|
||||
|
||||
if (state & NS_STATE_SVG_FILTERED) {
|
||||
aFrame->DeleteProperty(nsGkAtoms::filter);
|
||||
}
|
||||
|
||||
if (state & NS_STATE_SVG_MASKED) {
|
||||
aFrame->DeleteProperty(nsGkAtoms::mask);
|
||||
}
|
||||
|
||||
aFrame->RemoveStateBits(NS_STATE_SVG_CLIPPED_MASK |
|
||||
NS_STATE_SVG_FILTERED |
|
||||
NS_STATE_SVG_MASKED);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGUtils::WillModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
if (filter)
|
||||
InvalidateFilterRegion(aFrame);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGUtils::DidModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
|
||||
nsISVGValue::modificationType aModType)
|
||||
{
|
||||
nsISVGFilterFrame *filter;
|
||||
CallQueryInterface(observable, &filter);
|
||||
|
||||
if (filter) {
|
||||
InvalidateFilterRegion(aFrame);
|
||||
|
||||
if (aModType == nsISVGValue::mod_die) {
|
||||
aFrame->DeleteProperty(nsGkAtoms::filter);
|
||||
aFrame->RemoveStateBits(NS_STATE_SVG_FILTERED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
|
||||
{
|
||||
PRBool clipHit = PR_TRUE;
|
||||
|
||||
nsISVGChildFrame* SVGFrame;
|
||||
CallQueryInterface(aFrame, &SVGFrame);
|
||||
|
||||
if (aFrame->GetStateBits() & NS_STATE_SVG_CLIPPED_MASK) {
|
||||
nsISVGClipPathFrame *clip;
|
||||
clip = NS_STATIC_CAST(nsISVGClipPathFrame *,
|
||||
aFrame->GetProperty(nsGkAtoms::clipPath));
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
|
||||
clip->ClipHitTest(SVGFrame, matrix, x, y, &clipHit);
|
||||
}
|
||||
|
||||
return clipHit;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGUtils::HitTestChildren(nsIFrame *aFrame, float x, float y,
|
||||
nsIFrame **aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
for (nsIFrame* kid = aFrame->GetFirstChild(nsnull); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsISVGChildFrame* SVGFrame;
|
||||
CallQueryInterface(kid, &SVGFrame);
|
||||
if (SVGFrame) {
|
||||
nsIFrame* temp=nsnull;
|
||||
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
|
||||
if (NS_SUCCEEDED(rv) && temp) {
|
||||
*aResult = temp;
|
||||
// return NS_OK; can't return. we need reverse order but only
|
||||
// have a singly linked list...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*aResult && !HitTestClip(aFrame, x, y))
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISVGValue.h"
|
||||
|
||||
class nsPresContext;
|
||||
class nsIContent;
|
||||
|
@ -64,6 +65,8 @@ class nsIPresShell;
|
|||
class nsISVGRendererCanvas;
|
||||
class nsISVGOuterSVGFrame;
|
||||
class nsIDOMSVGAnimatedPreserveAspectRatio;
|
||||
class nsISVGValueObserver;
|
||||
class nsIAtom;
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
|
@ -72,6 +75,13 @@ class nsIDOMSVGAnimatedPreserveAspectRatio;
|
|||
// SVG Frame state bits
|
||||
#define NS_STATE_IS_OUTER_SVG 0x00100000
|
||||
|
||||
#define NS_STATE_SVG_CLIPPED_TRIVIAL 0x00200000
|
||||
#define NS_STATE_SVG_CLIPPED_COMPLEX 0x00400000
|
||||
#define NS_STATE_SVG_CLIPPED_MASK 0x00600000
|
||||
|
||||
#define NS_STATE_SVG_FILTERED 0x00800000
|
||||
#define NS_STATE_SVG_MASKED 0x01000000
|
||||
|
||||
class nsSVGUtils
|
||||
{
|
||||
public:
|
||||
|
@ -216,6 +226,43 @@ public:
|
|||
nsIDOMSVGAnimatedPreserveAspectRatio *aPreserveAspectRatio,
|
||||
PRBool aIgnoreAlign = PR_FALSE);
|
||||
|
||||
/* Paint frame with SVG effects */
|
||||
static void
|
||||
PaintChildWithEffects(nsISVGRendererCanvas *aCanvas, nsIFrame *aFrame);
|
||||
|
||||
/* Style change for effects (filter/clip/mask/opacity) - call when
|
||||
* the frame's style has changed to make sure the effects properties
|
||||
* stay in sync. */
|
||||
static void
|
||||
StyleEffects(nsIFrame *aFrame);
|
||||
|
||||
/* Modification events for effects (filter/clip/mask/opacity) - call
|
||||
* when observers on effects get called to make sure properties stay
|
||||
* in sync. */
|
||||
static void
|
||||
WillModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
|
||||
nsISVGValue::modificationType aModType);
|
||||
static void
|
||||
DidModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
|
||||
nsISVGValue::modificationType aModType);
|
||||
|
||||
/* Hit testing - check if point hits the clipPath of indicated
|
||||
* frame. Returns true of no clipPath set. */
|
||||
|
||||
static PRBool
|
||||
HitTestClip(nsIFrame *aFrame, float x, float y);
|
||||
|
||||
/* Hit testing - check if point hits any children of frame. */
|
||||
|
||||
static void
|
||||
HitTestChildren(nsIFrame *aFrame, float x, float y, nsIFrame **aResult);
|
||||
|
||||
/*
|
||||
* Returns the CanvasTM of the indicated frame, whether it's a
|
||||
* child or container SVG frame.
|
||||
*/
|
||||
static already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM(nsIFrame *aFrame);
|
||||
|
||||
private:
|
||||
/*
|
||||
* Returns the glyph fragment containing a particular character
|
||||
|
|
|
@ -129,8 +129,13 @@ interface nsISVGRendererCanvas : nsISupports
|
|||
|
||||
/**
|
||||
* Push/Pop surface as primary drawing surface.
|
||||
*
|
||||
* surface: surface to push
|
||||
* isSubSurface: boolean to tell whether this should be treated like
|
||||
* the "root" surface in terms of transformation correction
|
||||
* or as an absolute surface.
|
||||
*/
|
||||
void pushSurface(in nsISVGRendererSurface surface);
|
||||
void pushSurface(in nsISVGRendererSurface surface, in boolean isSubSurface);
|
||||
void popSurface();
|
||||
|
||||
/**
|
||||
|
@ -142,11 +147,9 @@ interface nsISVGRendererCanvas : nsISupports
|
|||
* Surface composition.
|
||||
*/
|
||||
void compositeSurface(in nsISVGRendererSurface surface,
|
||||
in unsigned long x, in unsigned long y,
|
||||
in float opacity);
|
||||
|
||||
void compositeSurfaceWithMask(in nsISVGRendererSurface surface,
|
||||
in unsigned long x, in unsigned long y,
|
||||
in nsISVGRendererSurface mask);
|
||||
|
||||
void compositeSurfaceMatrix(in nsISVGRendererSurface surface,
|
||||
|
|
|
@ -150,6 +150,7 @@ private:
|
|||
nsCOMPtr<imgIContainer> mContainer;
|
||||
nsCOMPtr<gfxIImageFrame> mBuffer;
|
||||
PRUint8 *mData;
|
||||
PRInt32 mSubSurfaceDepth;
|
||||
|
||||
PRUint16 mRenderMode;
|
||||
PRPackedBool mOwnsCR;
|
||||
|
@ -162,7 +163,7 @@ private:
|
|||
//----------------------------------------------------------------------
|
||||
// implementation:
|
||||
|
||||
nsSVGCairoCanvas::nsSVGCairoCanvas() : mData(nsnull)
|
||||
nsSVGCairoCanvas::nsSVGCairoCanvas() : mData(nsnull), mSubSurfaceDepth(0)
|
||||
{
|
||||
mOwnsCR = PR_FALSE;
|
||||
}
|
||||
|
@ -184,7 +185,7 @@ nsSVGCairoCanvas::~nsSVGCairoCanvas()
|
|||
nsresult
|
||||
nsSVGCairoCanvas::AdjustMatrixForInitialTransform(cairo_matrix_t* aMatrix)
|
||||
{
|
||||
if (mContextStack.Count() == 0)
|
||||
if (mSubSurfaceDepth == mContextStack.Count())
|
||||
cairo_matrix_multiply(aMatrix, aMatrix, &mInitialTransform);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -714,7 +715,8 @@ struct ctxEntry {
|
|||
|
||||
/** Implements pushSurface(in nsISVGRendererSurface surface); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
|
||||
nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface,
|
||||
PRBool isSubSurface)
|
||||
{
|
||||
nsCOMPtr<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
|
||||
if (!cairoSurface)
|
||||
|
@ -728,6 +730,10 @@ nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
|
|||
ctx->mWidth = mWidth;
|
||||
ctx->mHeight = mHeight;
|
||||
|
||||
// Once we go non-subsurface, all further pushes are forced absolute
|
||||
if (isSubSurface && mSubSurfaceDepth == mContextStack.Count())
|
||||
mSubSurfaceDepth++;
|
||||
|
||||
mContextStack.AppendElement(NS_STATIC_CAST(void*, ctx));
|
||||
|
||||
mCR = cairo_create(cairoSurface->GetSurface());
|
||||
|
@ -741,7 +747,7 @@ nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
|
|||
NS_IMETHODIMP
|
||||
nsSVGCairoCanvas::PopSurface()
|
||||
{
|
||||
PRUint32 count = mContextStack.Count();
|
||||
PRInt32 count = mContextStack.Count();
|
||||
if (count != 0) {
|
||||
cairo_destroy(mCR);
|
||||
ctxEntry *ctx = NS_STATIC_CAST(ctxEntry*, mContextStack[count - 1]);
|
||||
|
@ -750,6 +756,9 @@ nsSVGCairoCanvas::PopSurface()
|
|||
mHeight = ctx->mHeight;
|
||||
delete ctx;
|
||||
mContextStack.RemoveElementAt(count - 1);
|
||||
|
||||
if (mSubSurfaceDepth == count)
|
||||
mSubSurfaceDepth--;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -764,18 +773,18 @@ nsSVGCairoCanvas::GetSurfaceSize(PRUint32 *aWidth, PRUint32 *aHeight)
|
|||
}
|
||||
|
||||
/** Implements void compositeSurface(in nsISVGRendererSurface surface,
|
||||
in unsigned long x, in unsigned long y,
|
||||
in float opacity); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGCairoCanvas::CompositeSurface(nsISVGRendererSurface *aSurface,
|
||||
PRUint32 aX, PRUint32 aY, float aOpacity)
|
||||
float aOpacity)
|
||||
{
|
||||
nsCOMPtr<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
|
||||
if (!cairoSurface)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
cairo_save(mCR);
|
||||
cairo_translate(mCR, aX, aY);
|
||||
if (mSubSurfaceDepth == mContextStack.Count())
|
||||
cairo_translate(mCR, -mInitialTransform.x0, -mInitialTransform.y0);
|
||||
|
||||
cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0);
|
||||
cairo_paint_with_alpha(mCR, aOpacity);
|
||||
|
@ -785,12 +794,9 @@ nsSVGCairoCanvas::CompositeSurface(nsISVGRendererSurface *aSurface,
|
|||
}
|
||||
|
||||
/** Implements void compositeSurfaceWithMask(in nsISVGRendererSurface surface,
|
||||
in unsigned long x,
|
||||
in unsigned long y,
|
||||
in nsISVGRendererSurface mask); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGCairoCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface,
|
||||
PRUint32 aX, PRUint32 aY,
|
||||
nsISVGRendererSurface *aMask)
|
||||
{
|
||||
nsCOMPtr<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
|
||||
|
@ -799,7 +805,8 @@ nsSVGCairoCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface,
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
cairo_save(mCR);
|
||||
cairo_translate(mCR, aX, aY);
|
||||
if (mSubSurfaceDepth == mContextStack.Count())
|
||||
cairo_translate(mCR, -mInitialTransform.x0, -mInitialTransform.y0);
|
||||
|
||||
cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0);
|
||||
cairo_mask_surface(mCR, maskSurface->GetSurface(), 0.0, 0.0);
|
||||
|
|
Загрузка…
Ссылка в новой задаче