2008-08-07 18:34:43 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is the Mozilla SVG project.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is IBM Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* rocallahan@mozilla.com
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "nsSVGEffects.h"
|
|
|
|
#include "nsISupportsImpl.h"
|
|
|
|
#include "nsSVGOuterSVGFrame.h"
|
2008-09-30 17:51:05 -07:00
|
|
|
#include "nsSVGFilterFrame.h"
|
|
|
|
#include "nsSVGClipPathFrame.h"
|
|
|
|
#include "nsSVGMaskFrame.h"
|
2008-10-11 04:29:35 -07:00
|
|
|
#include "nsSVGTextPathFrame.h"
|
2008-10-22 02:09:03 -07:00
|
|
|
#include "nsCSSFrameConstructor.h"
|
2008-09-30 17:51:05 -07:00
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS1(nsSVGRenderingObserver, nsIMutationObserver)
|
|
|
|
|
|
|
|
nsSVGRenderingObserver::nsSVGRenderingObserver(nsIURI *aURI,
|
|
|
|
nsIFrame *aFrame)
|
|
|
|
: mElement(this), mFrame(aFrame),
|
|
|
|
mFramePresShell(aFrame->PresContext()->PresShell()),
|
|
|
|
mReferencedFrame(nsnull),
|
|
|
|
mReferencedFramePresShell(nsnull)
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
// Start watching the target element
|
|
|
|
mElement.Reset(aFrame->GetContent(), aURI);
|
|
|
|
if (mElement.get()) {
|
|
|
|
mElement.get()->AddMutationObserver(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::~nsSVGRenderingObserver()
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
if (mElement.get()) {
|
|
|
|
mElement.get()->RemoveMutationObserver(this);
|
|
|
|
}
|
2008-09-30 17:51:05 -07:00
|
|
|
if (mReferencedFrame && !mReferencedFramePresShell->IsDestroying()) {
|
|
|
|
nsSVGEffects::RemoveRenderingObserver(mReferencedFrame, this);
|
|
|
|
}
|
2008-08-07 18:34:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame*
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::GetReferencedFrame()
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
if (mReferencedFrame && !mReferencedFramePresShell->IsDestroying()) {
|
|
|
|
NS_ASSERTION(mElement.get() &&
|
|
|
|
static_cast<nsGenericElement*>(mElement.get())->GetPrimaryFrame() == mReferencedFrame,
|
|
|
|
"Cached frame is incorrect!");
|
|
|
|
return mReferencedFrame;
|
|
|
|
}
|
|
|
|
|
2008-08-07 18:34:43 -07:00
|
|
|
if (mElement.get()) {
|
|
|
|
nsIFrame *frame =
|
|
|
|
static_cast<nsGenericElement*>(mElement.get())->GetPrimaryFrame();
|
2008-09-30 17:51:05 -07:00
|
|
|
if (frame) {
|
|
|
|
mReferencedFrame = frame;
|
|
|
|
mReferencedFramePresShell = mReferencedFrame->PresContext()->PresShell();
|
|
|
|
nsSVGEffects::AddRenderingObserver(mReferencedFrame, this);
|
2008-08-07 18:34:43 -07:00
|
|
|
return frame;
|
2008-09-30 17:51:05 -07:00
|
|
|
}
|
2008-08-07 18:34:43 -07:00
|
|
|
}
|
2008-09-30 17:51:05 -07:00
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame*
|
|
|
|
nsSVGRenderingObserver::GetReferencedFrame(nsIAtom* aFrameType, PRBool* aOK)
|
|
|
|
{
|
|
|
|
nsIFrame* frame = GetReferencedFrame();
|
|
|
|
if (frame && frame->GetType() == aFrameType)
|
|
|
|
return frame;
|
2008-08-07 18:34:43 -07:00
|
|
|
if (aOK) {
|
|
|
|
*aOK = PR_FALSE;
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::DoUpdate()
|
|
|
|
{
|
|
|
|
if (mFramePresShell->IsDestroying()) {
|
|
|
|
// mFrame is no longer valid. Bail out.
|
|
|
|
mFrame = nsnull;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mReferencedFrame) {
|
|
|
|
nsSVGEffects::RemoveRenderingObserver(mReferencedFrame, this);
|
|
|
|
mReferencedFrame = nsnull;
|
|
|
|
mReferencedFramePresShell = nsnull;
|
|
|
|
}
|
|
|
|
if (mFrame && mFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
|
|
|
// Changes should propagate out to things that might be observing
|
|
|
|
// the referencing frame or its ancestors.
|
|
|
|
nsSVGEffects::InvalidateRenderingObservers(mFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGRenderingObserver::InvalidateViaReferencedFrame()
|
|
|
|
{
|
|
|
|
// Clear mReferencedFrame since the referenced frame has already
|
|
|
|
// dropped its reference back to us
|
|
|
|
mReferencedFrame = nsnull;
|
|
|
|
mReferencedFramePresShell = nsnull;
|
|
|
|
DoUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGRenderingObserver::AttributeChanged(nsIDocument *aDocument,
|
|
|
|
nsIContent *aContent,
|
|
|
|
PRInt32 aNameSpaceID,
|
|
|
|
nsIAtom *aAttribute,
|
|
|
|
PRInt32 aModType,
|
|
|
|
PRUint32 aStateMask)
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
DoUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::ContentAppended(nsIDocument *aDocument,
|
|
|
|
nsIContent *aContainer,
|
|
|
|
PRInt32 aNewIndexInContainer)
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
DoUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::ContentInserted(nsIDocument *aDocument,
|
|
|
|
nsIContent *aContainer,
|
|
|
|
nsIContent *aChild,
|
|
|
|
PRInt32 aIndexInContainer)
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
DoUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::ContentRemoved(nsIDocument *aDocument,
|
|
|
|
nsIContent *aContainer,
|
|
|
|
nsIContent *aChild,
|
|
|
|
PRInt32 aIndexInContainer)
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
DoUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED1(nsSVGFilterProperty,
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver,
|
2008-08-07 18:34:43 -07:00
|
|
|
nsISVGFilterProperty)
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGFilterFrame *
|
2008-10-10 06:14:05 -07:00
|
|
|
nsSVGFilterProperty::GetFilterFrame()
|
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
return static_cast<nsSVGFilterFrame *>
|
|
|
|
(GetReferencedFrame(nsGkAtoms::svgFilterFrame, nsnull));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
InvalidateAllContinuations(nsIFrame* aFrame)
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
for (nsIFrame* f = aFrame; f; f = f->GetNextContinuation()) {
|
|
|
|
f->InvalidateOverflowRect();
|
2008-08-07 18:34:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGFilterProperty::DoUpdate()
|
2008-09-30 04:28:20 -07:00
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::DoUpdate();
|
|
|
|
if (!mFrame)
|
2008-08-07 18:34:43 -07:00
|
|
|
return;
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
if (mFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
|
|
|
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(mFrame);
|
|
|
|
if (outerSVGFrame) {
|
2008-10-22 02:09:03 -07:00
|
|
|
mFramePresShell->FrameConstructor()->PostRestyleEvent(
|
|
|
|
mFrame->GetContent(), nsReStyleHint(0),
|
|
|
|
nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects));
|
2008-09-30 17:51:05 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
InvalidateAllContinuations(mFrame);
|
|
|
|
// Reflow so that changes in the filter overflow area get picked up
|
|
|
|
mFramePresShell->FrameNeedsReflow(
|
|
|
|
mFrame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
|
2008-09-30 04:28:20 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-10 06:14:05 -07:00
|
|
|
void
|
|
|
|
nsSVGMarkerProperty::DoUpdate()
|
|
|
|
{
|
|
|
|
nsSVGRenderingObserver::DoUpdate();
|
|
|
|
if (!mFrame)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (mFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
2008-10-16 00:48:55 -07:00
|
|
|
if (!(mFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
|
|
|
|
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(mFrame);
|
|
|
|
if (outerSVGFrame) {
|
|
|
|
// marker changes can change the covered region
|
|
|
|
outerSVGFrame->UpdateAndInvalidateCoveredRegion(mFrame);
|
|
|
|
}
|
2008-10-10 06:14:05 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
InvalidateAllContinuations(mFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-11 04:29:35 -07:00
|
|
|
void
|
|
|
|
nsSVGTextPathProperty::DoUpdate()
|
|
|
|
{
|
|
|
|
nsSVGRenderingObserver::DoUpdate();
|
|
|
|
if (!mFrame)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NS_ASSERTION(mFrame->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected");
|
|
|
|
|
|
|
|
if (mFrame->GetType() == nsGkAtoms::svgTextPathFrame) {
|
|
|
|
nsSVGTextPathFrame* textPathFrame = static_cast<nsSVGTextPathFrame*>(mFrame);
|
|
|
|
textPathFrame->NotifyGlyphMetricsChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-30 04:28:20 -07:00
|
|
|
void
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGPaintingProperty::DoUpdate()
|
2008-09-30 04:28:20 -07:00
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver::DoUpdate();
|
|
|
|
if (!mFrame)
|
2008-09-30 04:28:20 -07:00
|
|
|
return;
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
if (mFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
|
|
|
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(mFrame);
|
|
|
|
if (outerSVGFrame) {
|
|
|
|
outerSVGFrame->InvalidateCoveredRegion(mFrame);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
InvalidateAllContinuations(mFrame);
|
2008-09-30 04:28:20 -07:00
|
|
|
}
|
2008-08-07 18:34:43 -07:00
|
|
|
}
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
static nsSVGRenderingObserver *
|
2008-08-07 18:34:43 -07:00
|
|
|
CreateFilterProperty(nsIURI *aURI, nsIFrame *aFrame)
|
|
|
|
{ return new nsSVGFilterProperty(aURI, aFrame); }
|
|
|
|
|
2008-10-10 06:14:05 -07:00
|
|
|
static nsSVGRenderingObserver *
|
|
|
|
CreateMarkerProperty(nsIURI *aURI, nsIFrame *aFrame)
|
|
|
|
{ return new nsSVGMarkerProperty(aURI, aFrame); }
|
|
|
|
|
2008-10-11 04:29:35 -07:00
|
|
|
static nsSVGRenderingObserver *
|
|
|
|
CreateTextPathProperty(nsIURI *aURI, nsIFrame *aFrame)
|
|
|
|
{ return new nsSVGTextPathProperty(aURI, aFrame); }
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
static nsSVGRenderingObserver *
|
|
|
|
CreatePaintingProperty(nsIURI *aURI, nsIFrame *aFrame)
|
|
|
|
{ return new nsSVGPaintingProperty(aURI, aFrame); }
|
2008-08-07 18:34:43 -07:00
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
static nsSVGRenderingObserver *
|
2008-08-07 18:34:43 -07:00
|
|
|
GetEffectProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp,
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver * (* aCreate)(nsIURI *, nsIFrame *))
|
2008-08-07 18:34:43 -07:00
|
|
|
{
|
|
|
|
if (!aURI)
|
|
|
|
return nsnull;
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGRenderingObserver *prop =
|
|
|
|
static_cast<nsSVGRenderingObserver*>(aFrame->GetProperty(aProp));
|
2008-08-07 18:34:43 -07:00
|
|
|
if (prop)
|
|
|
|
return prop;
|
|
|
|
prop = aCreate(aURI, aFrame);
|
|
|
|
if (!prop)
|
|
|
|
return nsnull;
|
|
|
|
NS_ADDREF(prop);
|
|
|
|
aFrame->SetProperty(aProp,
|
|
|
|
static_cast<nsISupports*>(prop),
|
|
|
|
nsPropertyTable::SupportsDtorFunc);
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
2008-10-10 06:14:05 -07:00
|
|
|
nsSVGMarkerProperty *
|
|
|
|
nsSVGEffects::GetMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp)
|
|
|
|
{
|
|
|
|
return static_cast<nsSVGMarkerProperty*>(
|
|
|
|
GetEffectProperty(aURI, aFrame, aProp, CreateMarkerProperty));
|
|
|
|
}
|
|
|
|
|
2008-10-11 04:29:35 -07:00
|
|
|
nsSVGTextPathProperty *
|
|
|
|
nsSVGEffects::GetTextPathProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp)
|
|
|
|
{
|
|
|
|
return static_cast<nsSVGTextPathProperty*>(
|
|
|
|
GetEffectProperty(aURI, aFrame, aProp, CreateTextPathProperty));
|
|
|
|
}
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGPaintingProperty *
|
|
|
|
nsSVGEffects::GetPaintingProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp)
|
|
|
|
{
|
|
|
|
return static_cast<nsSVGPaintingProperty*>(
|
|
|
|
GetEffectProperty(aURI, aFrame, aProp, CreatePaintingProperty));
|
|
|
|
}
|
|
|
|
|
2008-08-07 18:34:43 -07:00
|
|
|
nsSVGEffects::EffectProperties
|
|
|
|
nsSVGEffects::GetEffectProperties(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
|
|
|
|
|
|
|
|
EffectProperties result;
|
|
|
|
const nsStyleSVGReset *style = aFrame->GetStyleSVGReset();
|
|
|
|
result.mFilter = static_cast<nsSVGFilterProperty*>
|
|
|
|
(GetEffectProperty(style->mFilter, aFrame, nsGkAtoms::filter, CreateFilterProperty));
|
2008-09-30 17:51:05 -07:00
|
|
|
result.mClipPath = GetPaintingProperty(style->mClipPath, aFrame, nsGkAtoms::clipPath);
|
|
|
|
result.mMask = GetPaintingProperty(style->mMask, aFrame, nsGkAtoms::mask);
|
2008-08-07 18:34:43 -07:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
nsSVGClipPathFrame *
|
2008-10-10 06:14:05 -07:00
|
|
|
nsSVGEffects::EffectProperties::GetClipPathFrame(PRBool *aOK)
|
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
if (!mClipPath)
|
|
|
|
return nsnull;
|
|
|
|
return static_cast<nsSVGClipPathFrame *>
|
|
|
|
(mClipPath->GetReferencedFrame(nsGkAtoms::svgClipPathFrame, aOK));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSVGMaskFrame *
|
2008-10-10 06:14:05 -07:00
|
|
|
nsSVGEffects::EffectProperties::GetMaskFrame(PRBool *aOK)
|
|
|
|
{
|
2008-09-30 17:51:05 -07:00
|
|
|
if (!mMask)
|
|
|
|
return nsnull;
|
|
|
|
return static_cast<nsSVGMaskFrame *>
|
|
|
|
(mMask->GetReferencedFrame(nsGkAtoms::svgMaskFrame, aOK));
|
|
|
|
}
|
|
|
|
|
2008-08-07 18:34:43 -07:00
|
|
|
void
|
|
|
|
nsSVGEffects::UpdateEffects(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
aFrame->DeleteProperty(nsGkAtoms::filter);
|
|
|
|
aFrame->DeleteProperty(nsGkAtoms::mask);
|
|
|
|
aFrame->DeleteProperty(nsGkAtoms::clipPath);
|
2008-09-30 17:51:05 -07:00
|
|
|
|
2008-10-10 06:14:05 -07:00
|
|
|
aFrame->DeleteProperty(nsGkAtoms::marker_start);
|
|
|
|
aFrame->DeleteProperty(nsGkAtoms::marker_mid);
|
|
|
|
aFrame->DeleteProperty(nsGkAtoms::marker_end);
|
|
|
|
|
2008-09-30 17:51:05 -07:00
|
|
|
aFrame->DeleteProperty(nsGkAtoms::stroke);
|
|
|
|
aFrame->DeleteProperty(nsGkAtoms::fill);
|
2008-10-22 02:09:03 -07:00
|
|
|
|
|
|
|
// Ensure that the filter's covered area is recalculated correctly
|
|
|
|
// We can't do that in DoUpdate as the referenced frame may not be valid
|
|
|
|
const nsStyleSVGReset *style = aFrame->GetStyleSVGReset();
|
|
|
|
if (style->mFilter) {
|
|
|
|
GetEffectProperty(style->mFilter, aFrame, nsGkAtoms::filter, CreateFilterProperty);
|
|
|
|
}
|
2008-08-07 18:34:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsSVGFilterProperty *
|
|
|
|
nsSVGEffects::GetFilterProperty(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
|
|
|
|
|
|
|
|
if (!aFrame->GetStyleSVGReset()->mFilter)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
return static_cast<nsSVGFilterProperty *>(aFrame->GetProperty(nsGkAtoms::filter));
|
|
|
|
}
|
2008-09-30 17:51:05 -07:00
|
|
|
|
2008-10-20 23:50:05 -07:00
|
|
|
static PLDHashOperator
|
2008-09-30 17:51:05 -07:00
|
|
|
GatherEnumerator(nsVoidPtrHashKey* aEntry, void* aArg)
|
|
|
|
{
|
|
|
|
nsTArray<nsSVGRenderingObserver*>* array =
|
|
|
|
static_cast<nsTArray<nsSVGRenderingObserver*>*>(aArg);
|
|
|
|
array->AppendElement(static_cast<nsSVGRenderingObserver*>(
|
|
|
|
const_cast<void*>(aEntry->GetKey())));
|
|
|
|
return PL_DHASH_REMOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGRenderingObserverList::InvalidateAll()
|
|
|
|
{
|
|
|
|
if (mObservers.Count() == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsAutoTArray<nsSVGRenderingObserver*,10> observers;
|
|
|
|
mObservers.EnumerateEntries(GatherEnumerator, &observers);
|
|
|
|
for (PRUint32 i = 0; i < observers.Length(); ++i) {
|
|
|
|
observers[i]->InvalidateViaReferencedFrame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsSVGRenderingObserverList *
|
|
|
|
GetObserverList(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
if (!(aFrame->GetStateBits() & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS))
|
|
|
|
return nsnull;
|
|
|
|
return static_cast<nsSVGRenderingObserverList*>(aFrame->GetProperty(nsGkAtoms::observer));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGEffects::AddRenderingObserver(nsIFrame *aFrame, nsSVGRenderingObserver *aObserver)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation");
|
|
|
|
|
|
|
|
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
|
|
|
if (!observerList) {
|
|
|
|
observerList = new nsSVGRenderingObserverList();
|
|
|
|
if (!observerList)
|
|
|
|
return;
|
|
|
|
for (nsIFrame* f = aFrame; f; f = f->GetNextContinuation()) {
|
|
|
|
f->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS);
|
|
|
|
}
|
|
|
|
aFrame->SetProperty(nsGkAtoms::observer, observerList);
|
|
|
|
}
|
|
|
|
observerList->Add(aObserver);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGEffects::RemoveRenderingObserver(nsIFrame *aFrame, nsSVGRenderingObserver *aObserver)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation");
|
|
|
|
|
|
|
|
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
|
|
|
if (observerList) {
|
|
|
|
observerList->Remove(aObserver);
|
|
|
|
// Don't remove the property even if the observer list is empty.
|
|
|
|
// This might not be a good time to modify the frame property
|
|
|
|
// hashtables.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation");
|
|
|
|
|
|
|
|
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
|
|
|
if (observerList) {
|
|
|
|
observerList->InvalidateAll();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check ancestor SVG containers. The root frame cannot be of type
|
|
|
|
// eSVGContainer so we don't have to check f for null here.
|
|
|
|
for (nsIFrame *f = aFrame->GetParent();
|
|
|
|
f->IsFrameOfType(nsIFrame::eSVGContainer); f = f->GetParent()) {
|
|
|
|
observerList = GetObserverList(f);
|
|
|
|
if (observerList) {
|
|
|
|
observerList->InvalidateAll();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
|
|
|
if (observerList) {
|
|
|
|
observerList->InvalidateAll();
|
|
|
|
}
|
|
|
|
}
|