mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 329758 - changing markers via DOM does not cause a refresh. r=tor,sr=roc
This commit is contained in:
parent
d0dee808f7
commit
fc0e9059bf
@ -137,11 +137,15 @@ NS_GetSVGClipPathFrame(nsISVGClipPathFrame **aResult,
|
||||
NS_WARNING("No document for this content!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsIPresShell *aPresShell = myDoc->GetShellAt(0);
|
||||
nsIPresShell *presShell = myDoc->GetShellAt(0);
|
||||
if (!presShell) {
|
||||
NS_WARNING("no presshell");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Find the referenced frame
|
||||
nsIFrame *cpframe;
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&cpframe, aURI, aContent, aPresShell)))
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&cpframe, aURI, aContent, presShell)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIAtom* frameType = cpframe->GetType();
|
||||
|
@ -150,11 +150,15 @@ NS_GetSVGFilterFrame(nsISVGFilterFrame **aResult,
|
||||
NS_WARNING("No document for this content!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsIPresShell *aPresShell = myDoc->GetShellAt(0);
|
||||
nsIPresShell *presShell = myDoc->GetShellAt(0);
|
||||
if (!presShell) {
|
||||
NS_WARNING("no presshell");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Find the referenced frame
|
||||
nsIFrame *filter;
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&filter, aURI, aContent, aPresShell)))
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&filter, aURI, aContent, presShell)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIAtom* frameType = filter->GetType();
|
||||
|
@ -55,18 +55,21 @@
|
||||
#include "nsSVGMarkerFrame.h"
|
||||
#include "nsSVGPathGeometryFrame.h"
|
||||
#include "nsISVGRendererCanvas.h"
|
||||
#include "nsSVGValue.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGMatrix.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
class nsSVGMarkerFrame : public nsSVGDefsFrame,
|
||||
public nsSVGValue,
|
||||
public nsISVGMarkerFrame
|
||||
{
|
||||
protected:
|
||||
friend nsIFrame*
|
||||
NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
|
||||
|
||||
virtual ~nsSVGMarkerFrame();
|
||||
NS_IMETHOD InitSVG();
|
||||
|
||||
public:
|
||||
@ -77,6 +80,10 @@ public:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
|
||||
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
|
||||
|
||||
// nsISVGValue interface:
|
||||
NS_IMETHOD SetValueString(const nsAString &aValue) { return NS_OK; }
|
||||
NS_IMETHOD GetValueString(nsAString& aValue) { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
// nsIFrame interface:
|
||||
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
@ -131,6 +138,7 @@ private:
|
||||
};
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsSVGMarkerFrame)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVGValue)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVGMarkerFrame)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsSVGDefsFrame)
|
||||
|
||||
@ -152,11 +160,15 @@ NS_GetSVGMarkerFrame(nsISVGMarkerFrame **aResult,
|
||||
NS_WARNING("No document for this content!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsIPresShell *aPresShell = myDoc->GetShellAt(0);
|
||||
nsIPresShell *presShell = myDoc->GetShellAt(0);
|
||||
if (!presShell) {
|
||||
NS_WARNING("no presshell");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Find the referenced frame
|
||||
nsIFrame *marker;
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&marker, aURI, aContent, aPresShell)))
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&marker, aURI, aContent, presShell)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIAtom* frameType = marker->GetType();
|
||||
@ -167,6 +179,13 @@ NS_GetSVGMarkerFrame(nsISVGMarkerFrame **aResult,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsSVGMarkerFrame::~nsSVGMarkerFrame()
|
||||
{
|
||||
WillModify();
|
||||
// Notify the world that we're dying
|
||||
DidModify(mod_die);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGMarkerFrame::InitSVG()
|
||||
{
|
||||
@ -249,7 +268,8 @@ nsSVGMarkerFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||
aAttribute == nsGkAtoms::markerHeight ||
|
||||
aAttribute == nsGkAtoms::orient ||
|
||||
aAttribute == nsGkAtoms::viewBox)) {
|
||||
// XXX: marker frame should be a nsSVGValue and call DidModify() here
|
||||
WillModify();
|
||||
DidModify();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -127,11 +127,15 @@ NS_GetSVGMaskFrame(nsISVGMaskFrame **aResult,
|
||||
NS_WARNING("No document for this content!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsIPresShell *aPresShell = myDoc->GetShellAt(0);
|
||||
nsIPresShell *presShell = myDoc->GetShellAt(0);
|
||||
if (!presShell) {
|
||||
NS_WARNING("no presshell");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Find the referenced frame
|
||||
nsIFrame *cpframe;
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&cpframe, aURI, aContent, aPresShell)))
|
||||
if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&cpframe, aURI, aContent, presShell)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIAtom* frameType = cpframe->GetType();
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include "nsIDOMSVGMatrix.h"
|
||||
#include "nsISVGRendererPathBuilder.h"
|
||||
#include "nsISVGMarkable.h"
|
||||
#include "nsSVGMarkerFrame.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsISVGPathFlatten.h"
|
||||
|
@ -66,6 +66,18 @@
|
||||
#include "nsISVGRendererSurface.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
||||
struct nsSVGMarkerProperty {
|
||||
nsISVGMarkerFrame *mMarkerStart;
|
||||
nsISVGMarkerFrame *mMarkerMid;
|
||||
nsISVGMarkerFrame *mMarkerEnd;
|
||||
|
||||
nsSVGMarkerProperty()
|
||||
: mMarkerStart(nsnull),
|
||||
mMarkerMid(nsnull),
|
||||
mMarkerEnd(nsnull)
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsSVGPathGeometryFrame
|
||||
|
||||
@ -99,6 +111,9 @@ nsSVGPathGeometryFrame::~nsSVGPathGeometryFrame()
|
||||
if (mStrokePattern) {
|
||||
NS_REMOVE_SVGVALUE_OBSERVER(mStrokePattern);
|
||||
}
|
||||
if (GetStateBits() & NS_STATE_SVG_HAS_MARKERS) {
|
||||
DeleteProperty(nsGkAtoms::marker);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -169,6 +184,11 @@ nsSVGPathGeometryFrame::DidSetStyleContext()
|
||||
}
|
||||
nsSVGUtils::StyleEffects(this);
|
||||
|
||||
if (GetStateBits() & NS_STATE_SVG_HAS_MARKERS) {
|
||||
DeleteProperty(nsGkAtoms::marker);
|
||||
RemoveStateBits(NS_STATE_SVG_HAS_MARKERS);
|
||||
}
|
||||
|
||||
// XXX: we'd like to use the style_hint mechanism and the
|
||||
// ContentStateChanged/AttributeChanged functions for style changes
|
||||
// to get slightly finer granularity, but unfortunately the
|
||||
@ -192,32 +212,102 @@ nsSVGPathGeometryFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
return !(aFlags & ~nsIFrame::eSVG);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGChildFrame methods
|
||||
|
||||
// marker helper
|
||||
static void
|
||||
RemoveMarkerObserver(nsSVGMarkerProperty *property,
|
||||
nsIFrame *aFrame,
|
||||
nsISVGMarkerFrame *marker)
|
||||
{
|
||||
if (!marker) return;
|
||||
if (property->mMarkerStart == marker)
|
||||
property->mMarkerStart = nsnull;
|
||||
if (property->mMarkerMid == marker)
|
||||
property->mMarkerMid = nsnull;
|
||||
if (property->mMarkerEnd == marker)
|
||||
property->mMarkerEnd = nsnull;
|
||||
nsSVGUtils::RemoveObserver(aFrame, marker);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkerPropertyDtor(void *aObject, nsIAtom *aPropertyName,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
nsSVGMarkerProperty *property = NS_STATIC_CAST(nsSVGMarkerProperty *,
|
||||
aPropertyValue);
|
||||
nsIFrame *frame = NS_STATIC_CAST(nsIFrame *, aObject);
|
||||
RemoveMarkerObserver(property, frame, property->mMarkerStart);
|
||||
RemoveMarkerObserver(property, frame, property->mMarkerMid);
|
||||
RemoveMarkerObserver(property, frame, property->mMarkerEnd);
|
||||
delete property;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGPathGeometryFrame::GetMarkerFrames(nsISVGMarkerFrame **markerStart,
|
||||
nsISVGMarkerFrame **markerMid,
|
||||
nsISVGMarkerFrame **markerEnd)
|
||||
{
|
||||
nsIURI *aURI;
|
||||
*markerStart = *markerMid = *markerEnd = nsnull;
|
||||
|
||||
*markerStart = *markerMid = *markerEnd = NULL;
|
||||
|
||||
aURI = GetStyleSVG()->mMarkerEnd;
|
||||
if (aURI)
|
||||
NS_GetSVGMarkerFrame(markerEnd, aURI, mContent);
|
||||
|
||||
aURI = GetStyleSVG()->mMarkerMid;
|
||||
if (aURI)
|
||||
NS_GetSVGMarkerFrame(markerMid, aURI, mContent);
|
||||
|
||||
aURI = GetStyleSVG()->mMarkerStart;
|
||||
if (aURI)
|
||||
NS_GetSVGMarkerFrame(markerStart, aURI, mContent);
|
||||
if (GetStateBits() & NS_STATE_SVG_HAS_MARKERS) {
|
||||
nsSVGMarkerProperty *property;
|
||||
property = NS_STATIC_CAST(nsSVGMarkerProperty *,
|
||||
GetProperty(nsGkAtoms::marker));
|
||||
|
||||
if (property) {
|
||||
*markerStart = property->mMarkerStart;
|
||||
*markerMid = property->mMarkerMid;
|
||||
*markerEnd = property->mMarkerEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGPathGeometryFrame::GetMarkerFromStyle(nsISVGMarkerFrame **aResult,
|
||||
nsSVGMarkerProperty *property,
|
||||
nsIURI *aURI)
|
||||
{
|
||||
if (aURI && !*aResult) {
|
||||
nsISVGMarkerFrame *marker;
|
||||
NS_GetSVGMarkerFrame(&marker, aURI, GetContent());
|
||||
if (marker) {
|
||||
if (property->mMarkerStart != marker &&
|
||||
property->mMarkerMid != marker &&
|
||||
property->mMarkerEnd != marker)
|
||||
nsSVGUtils::AddObserver(NS_STATIC_CAST(nsIFrame *, this), marker);
|
||||
*aResult = marker;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGPathGeometryFrame::UpdateMarkerProperty()
|
||||
{
|
||||
const nsStyleSVG *style = GetStyleSVG();
|
||||
|
||||
if (style->mMarkerStart || style->mMarkerMid || style->mMarkerEnd) {
|
||||
|
||||
nsSVGMarkerProperty *property;
|
||||
if (GetStateBits() & NS_STATE_SVG_HAS_MARKERS) {
|
||||
property = NS_STATIC_CAST(nsSVGMarkerProperty *,
|
||||
GetProperty(nsGkAtoms::marker));
|
||||
} else {
|
||||
property = new nsSVGMarkerProperty;
|
||||
if (!property) {
|
||||
NS_ERROR("Could not create marker property");
|
||||
return;
|
||||
}
|
||||
SetProperty(nsGkAtoms::marker, property, MarkerPropertyDtor);
|
||||
AddStateBits(NS_STATE_SVG_HAS_MARKERS);
|
||||
}
|
||||
GetMarkerFromStyle(&property->mMarkerStart, property, style->mMarkerStart);
|
||||
GetMarkerFromStyle(&property->mMarkerMid, property, style->mMarkerMid);
|
||||
GetMarkerFromStyle(&property->mMarkerEnd, property, style->mMarkerEnd);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGChildFrame methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
{
|
||||
@ -231,6 +321,8 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas)
|
||||
CallQueryInterface(this, &markable);
|
||||
|
||||
if (markable) {
|
||||
// Marker Property is added lazily and may have been removed by a restyle
|
||||
UpdateMarkerProperty();
|
||||
nsISVGMarkerFrame *markerEnd, *markerMid, *markerStart;
|
||||
GetMarkerFrames(&markerStart, &markerMid, &markerEnd);
|
||||
|
||||
@ -370,7 +462,7 @@ NS_IMETHODIMP
|
||||
nsSVGPathGeometryFrame::NotifyRedrawUnsuspended()
|
||||
{
|
||||
if (mUpdateFlags != 0)
|
||||
UpdateGraphic(0);
|
||||
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_NOTHING);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -463,6 +555,20 @@ nsSVGPathGeometryFrame::DidModifySVGObservable (nsISVGValue* observable,
|
||||
}
|
||||
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_STROKE_PAINT);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsISVGMarkerFrame *marker;
|
||||
CallQueryInterface(observable, &marker);
|
||||
|
||||
if (marker) {
|
||||
if (aModType == nsISVGValue::mod_die)
|
||||
RemoveMarkerObserver(NS_STATIC_CAST(nsSVGMarkerProperty *,
|
||||
GetProperty(nsGkAtoms::marker)),
|
||||
this,
|
||||
marker);
|
||||
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_NOTHING);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -56,6 +56,7 @@ class nsIDOMSVGMatrix;
|
||||
class nsISVGRendererRegion;
|
||||
class nsISVGMarkerFrame;
|
||||
class nsISVGFilterFrame;
|
||||
struct nsSVGMarkerProperty;
|
||||
|
||||
typedef nsFrame nsSVGPathGeometryFrameBase;
|
||||
|
||||
@ -144,6 +145,10 @@ private:
|
||||
void GetMarkerFrames(nsISVGMarkerFrame **markerStart,
|
||||
nsISVGMarkerFrame **markerMid,
|
||||
nsISVGMarkerFrame **markerEnd);
|
||||
void GetMarkerFromStyle(nsISVGMarkerFrame **aResult,
|
||||
nsSVGMarkerProperty *property,
|
||||
nsIURI *aURI);
|
||||
void UpdateMarkerProperty();
|
||||
|
||||
nsCOMPtr<nsISVGRendererPathGeometry> mGeometry;
|
||||
PRUint32 mUpdateFlags;
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "nsIDOMSVGPoint.h"
|
||||
#include "nsISVGRendererPathBuilder.h"
|
||||
#include "nsISVGMarkable.h"
|
||||
#include "nsSVGMarkerFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "nsIDOMSVGPoint.h"
|
||||
#include "nsISVGRendererPathBuilder.h"
|
||||
#include "nsISVGMarkable.h"
|
||||
#include "nsSVGMarkerFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -775,11 +775,8 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// Effect helper functions
|
||||
|
||||
static void
|
||||
AddObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
void
|
||||
nsSVGUtils::AddObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
{
|
||||
nsISVGValueObserver *observer = nsnull;
|
||||
nsISVGValue *v = nsnull;
|
||||
@ -789,8 +786,8 @@ AddObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
v->AddObserver(observer);
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
void
|
||||
nsSVGUtils::RemoveObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
{
|
||||
nsISVGValueObserver *observer = nsnull;
|
||||
nsISVGValue *v = nsnull;
|
||||
@ -800,12 +797,17 @@ RemoveObserver(nsISupports *aObserver, nsISupports *aTarget)
|
||||
v->RemoveObserver(observer);
|
||||
}
|
||||
|
||||
// ************************************************************
|
||||
// Effect helper functions
|
||||
|
||||
static void
|
||||
FilterPropertyDtor(void *aObject, nsIAtom *aPropertyName,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
nsSVGFilterProperty *property = (nsSVGFilterProperty *)aPropertyValue;
|
||||
RemoveObserver((nsIFrame *)aObject, property->mFilter);
|
||||
nsSVGFilterProperty *property = NS_STATIC_CAST(nsSVGFilterProperty *,
|
||||
aPropertyValue);
|
||||
nsSVGUtils::RemoveObserver(NS_STATIC_CAST(nsIFrame *, aObject),
|
||||
property->mFilter);
|
||||
delete property;
|
||||
}
|
||||
|
||||
@ -830,8 +832,12 @@ AddEffectProperties(nsIFrame *aFrame)
|
||||
nsISVGFilterFrame *filter;
|
||||
NS_GetSVGFilterFrame(&filter, style->mFilter, aFrame->GetContent());
|
||||
if (filter) {
|
||||
AddObserver(aFrame, filter);
|
||||
nsSVGUtils::AddObserver(aFrame, filter);
|
||||
nsSVGFilterProperty *property = new nsSVGFilterProperty;
|
||||
if (!property) {
|
||||
NS_ERROR("Could not create filter property");
|
||||
return;
|
||||
}
|
||||
property->mFilter = filter;
|
||||
filter->GetInvalidationRegion(aFrame, getter_AddRefs(property->mFilterRegion));
|
||||
aFrame->SetProperty(nsGkAtoms::filter, property, FilterPropertyDtor);
|
||||
|
@ -82,6 +82,8 @@ class nsIAtom;
|
||||
#define NS_STATE_SVG_FILTERED 0x00800000
|
||||
#define NS_STATE_SVG_MASKED 0x01000000
|
||||
|
||||
#define NS_STATE_SVG_HAS_MARKERS 0x02000000
|
||||
|
||||
class nsSVGUtils
|
||||
{
|
||||
public:
|
||||
@ -257,6 +259,14 @@ public:
|
||||
static void
|
||||
HitTestChildren(nsIFrame *aFrame, float x, float y, nsIFrame **aResult);
|
||||
|
||||
/* Add observation of an nsISVGValue to an nsISVGValueObserver */
|
||||
static void
|
||||
AddObserver(nsISupports *aObserver, nsISupports *aTarget);
|
||||
|
||||
/* Remove observation of an nsISVGValue from an nsISVGValueObserver */
|
||||
static void
|
||||
RemoveObserver(nsISupports *aObserver, nsISupports *aTarget);
|
||||
|
||||
/*
|
||||
* Returns the CanvasTM of the indicated frame, whether it's a
|
||||
* child or container SVG frame.
|
||||
|
Loading…
Reference in New Issue
Block a user