Bug 390379 - Implement feImage. p=tor,longsonr r=longsonr, sr=roc a=dsicore

This commit is contained in:
tor@cs.brown.edu 2008-01-02 12:49:13 -08:00
Родитель d61a3d19f7
Коммит aa46adf459
11 изменённых файлов: 420 добавлений и 5 удалений

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

@ -127,8 +127,8 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument)
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x42f3a894, 0xe5d4, 0x44b1, \
{ 0x96, 0x34, 0x73, 0x8f, 0xf8, 0xbe, 0x5d, 0x9b } }
{ 0xdfcef311, 0xba28, 0x4600, \
{ 0xbe, 0xff, 0x2f, 0x9d, 0x42, 0x77, 0x07, 0x4e } }
// hack to make egcs / gcc 2.95.2 happy
class nsINode_base : public nsPIDOMEventTarget {
@ -684,6 +684,11 @@ protected:
return slots;
}
nsTObserverArray<nsIMutationObserver*> *GetMutationObservers()
{
return HasSlots() ? &FlagsAsSlots()->mMutationObservers : nsnull;
}
PRBool IsEditableInternal() const;
virtual PRBool IsEditableExternal() const
{

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

@ -178,6 +178,7 @@ INCLUDES += \
-I$(srcdir)/../../../events/src \
-I$(srcdir)/../../../html/content/src \
-I$(topsrcdir)/content/xbl/src \
-I$(topsrcdir)/gfx/src/thebes \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT

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

@ -158,6 +158,9 @@ nsresult
NS_NewSVGFEDiffuseLightingElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFESpecularLightingElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFEImageElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
@ -278,8 +281,9 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
return NS_NewSVGFEDiffuseLightingElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feSpecularLighting)
return NS_NewSVGFESpecularLightingElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feDisplacementMap ||
name == nsGkAtoms::feImage)
if (name == nsGkAtoms::feImage)
return NS_NewSVGFEImageElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feDisplacementMap)
return NS_NewSVGFEUnimplementedMOZElement(aResult, aNodeInfo);
if (name == nsGkAtoms::pattern)
return NS_NewSVGPatternElement(aResult, aNodeInfo);

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

@ -227,6 +227,22 @@ nsSVGFilterElement::IsAttributeMapped(const nsIAtom* name) const
nsSVGGraphicElementBase::IsAttributeMapped(name);
}
void
nsSVGFilterElement::Invalidate()
{
nsTObserverArray<nsIMutationObserver*> *observers = GetMutationObservers();
if (observers && !observers->IsEmpty()) {
nsTObserverArray<nsIMutationObserver*>::ForwardIterator iter(*observers);
while (iter.HasMore()) {
nsCOMPtr<nsIMutationObserver> obs(iter.GetNext());
nsCOMPtr<nsISVGFilterProperty> filter = do_QueryInterface(obs);
if (filter)
filter->Invalidate();
}
}
}
//----------------------------------------------------------------------
// nsSVGElement methods

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

@ -80,6 +80,9 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
// Invalidate users of this filter
void Invalidate();
protected:
virtual PRBool ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,

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

@ -60,6 +60,20 @@
#include "nsIFrame.h"
#include "gfxContext.h"
#include "nsSVGLengthList.h"
#include "nsIDOMSVGURIReference.h"
#include "nsImageLoadingContent.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#if defined(XP_WIN) && !defined(NOUSER)
// Prevent Windows redefining LoadImage
#define NOUSER
#endif
#include "nsThebesImage.h"
#include "nsSVGAnimatedPreserveAspectRatio.h"
#include "nsSVGPreserveAspectRatio.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsSVGMatrix.h"
#include "nsSVGFilterElement.h"
//--------------------Filter Resource-----------------------
/**
@ -5144,6 +5158,333 @@ nsSVGFESpecularLightingElement::LightPixel(const float *N, const float *L,
}
}
//---------------------Image------------------------
typedef nsSVGFE nsSVGFEImageElementBase;
class nsSVGFEImageElement : public nsSVGFEImageElementBase,
public nsIDOMSVGFEImageElement,
public nsISVGFilter,
public nsIDOMSVGURIReference,
public nsImageLoadingContent
{
protected:
friend nsresult NS_NewSVGFEImageElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGFEImageElement(nsINodeInfo* aNodeInfo);
virtual ~nsSVGFEImageElement();
nsresult Init();
public:
virtual PRBool SubregionIsUnionOfRegions() { return PR_FALSE; }
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
// FE Base
NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEImageElementBase::)
// nsISVGFilter
NS_IMETHOD Filter(nsSVGFilterInstance *instance);
NS_IMETHOD GetRequirements(PRUint32 *aRequirements);
NS_DECL_NSIDOMSVGFEIMAGEELEMENT
NS_DECL_NSIDOMSVGURIREFERENCE
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEImageElementBase::)
NS_FORWARD_NSIDOMNODE(nsSVGFEImageElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGFEImageElementBase::)
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual PRInt32 IntrinsicState() const;
// imgIDecoderObserver
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
const PRUnichar *statusArg);
// imgIContainerObserver
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsRect * dirtyRect);
// imgIContainerObserver
NS_IMETHOD OnStartContainer(imgIRequest *aRequest,
imgIContainer *aContainer);
private:
// Invalidate users of the filter containing this element.
void Invalidate();
protected:
virtual PRBool OperatesOnSRGB(nsIDOMSVGAnimatedString*) { return PR_TRUE; }
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> mPreserveAspectRatio;
};
NS_IMPL_NS_NEW_SVG_ELEMENT(FEImage)
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGFEImageElement,nsSVGFEImageElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGFEImageElement,nsSVGFEImageElementBase)
NS_INTERFACE_MAP_BEGIN(nsSVGFEImageElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEImageElement)
NS_INTERFACE_MAP_ENTRY(nsISVGFilter)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGURIReference)
NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver)
NS_INTERFACE_MAP_ENTRY(nsIImageLoadingContent)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEImageElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGFEImageElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGFEImageElement::nsSVGFEImageElement(nsINodeInfo *aNodeInfo)
: nsSVGFEImageElementBase(aNodeInfo)
{
}
nsSVGFEImageElement::~nsSVGFEImageElement()
{
DestroyImageLoadingContent();
}
nsresult
nsSVGFEImageElement::Init()
{
nsresult rv = nsSVGFEImageElementBase::Init();
NS_ENSURE_SUCCESS(rv,rv);
{
rv = NS_NewSVGAnimatedString(getter_AddRefs(mHref));
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::href, mHref, kNameSpaceID_XLink);
NS_ENSURE_SUCCESS(rv,rv);
}
{
nsCOMPtr<nsIDOMSVGPreserveAspectRatio> preserveAspectRatio;
rv = NS_NewSVGPreserveAspectRatio(getter_AddRefs(preserveAspectRatio));
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedPreserveAspectRatio(
getter_AddRefs(mPreserveAspectRatio),
preserveAspectRatio);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::preserveAspectRatio,
mPreserveAspectRatio);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv;
}
NS_IMETHODIMP
nsSVGFEImageElement::GetRequirements(PRUint32 *aRequirements)
{
*aRequirements = 0;
return NS_OK;
}
//----------------------------------------------------------------------
// nsIContent methods:
nsresult
nsSVGFEImageElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::href) {
nsAutoString href;
if (GetAttr(kNameSpaceID_XLink, nsGkAtoms::href, href)) {
// Note: no need to notify here; since we're just now being bound
// we don't have any frames or anything yet.
LoadImage(href, PR_FALSE, PR_FALSE);
}
}
return nsSVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
nsresult
nsSVGFEImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsresult rv = nsSVGFEImageElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
nsAutoString href;
if (GetAttr(kNameSpaceID_XLink, nsGkAtoms::href, href)) {
// Note: no need to notify here; since we're just now being bound
// we don't have any frames or anything yet.
LoadImage(href, PR_FALSE, PR_FALSE);
}
return rv;
}
PRInt32
nsSVGFEImageElement::IntrinsicState() const
{
return nsSVGFEImageElementBase::IntrinsicState() |
nsImageLoadingContent::ImageState();
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEImageElement)
//----------------------------------------------------------------------
// nsIDOMSVGURIReference methods:
/* readonly attribute nsIDOMSVGAnimatedString href; */
NS_IMETHODIMP
nsSVGFEImageElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
{
*aHref = mHref;
NS_IF_ADDREF(*aHref);
return NS_OK;
}
//----------------------------------------------------------------------
// nsIDOMSVGFEImageElement methods
NS_IMETHODIMP
nsSVGFEImageElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsRefPtr<gfxImageSurface> targetSurface;
nsSVGFilterResource fr(this, instance);
nsIDOMSVGAnimatedString* sourceGraphic = nsnull;
rv = NS_NewSVGAnimatedString(&sourceGraphic);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireSourceImage(sourceGraphic, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData,
getter_AddRefs(targetSurface));
NS_ENSURE_SUCCESS(rv, rv);
nsRect rect = fr.GetFilterSubregion();
#ifdef DEBUG_tor
fprintf(stderr, "FILTER IMAGE rect: %d,%d %dx%d\n",
rect.x, rect.y, rect.width, rect.height);
#endif
nsCOMPtr<imgIRequest> currentRequest;
GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(currentRequest));
nsCOMPtr<imgIContainer> imageContainer;
if (currentRequest)
currentRequest->GetImage(getter_AddRefs(imageContainer));
nsCOMPtr<gfxIImageFrame> currentFrame;
if (imageContainer)
imageContainer->GetCurrentFrame(getter_AddRefs(currentFrame));
gfxASurface *thebesSurface = nsnull;
if (currentFrame) {
nsCOMPtr<nsIImage> img(do_GetInterface(currentFrame));
nsThebesImage *thebesImage = nsnull;
if (img)
thebesImage = static_cast<nsThebesImage*>(img.get());
if (thebesImage)
thebesSurface = thebesImage->ThebesSurface();
}
if (thebesSurface) {
PRInt32 x, y, nativeWidth, nativeHeight;
currentFrame->GetX(&x);
currentFrame->GetY(&y);
currentFrame->GetWidth(&nativeWidth);
currentFrame->GetHeight(&nativeHeight);
nsCOMPtr<nsIDOMSVGMatrix> trans;
trans = nsSVGUtils::GetViewBoxTransform(rect.width, rect.height,
x, y,
nativeWidth, nativeHeight,
mPreserveAspectRatio);
nsCOMPtr<nsIDOMSVGMatrix> xy, fini;
NS_NewSVGMatrix(getter_AddRefs(xy), 1, 0, 0, 1, rect.x, rect.y);
xy->Multiply(trans, getter_AddRefs(fini));
gfxContext ctx(targetSurface);
nsSVGUtils::CompositeSurfaceMatrix(&ctx, thebesSurface, fini, 1.0);
}
return NS_OK;
}
//----------------------------------------------------------------------
// imgIDecoderObserver methods
NS_IMETHODIMP
nsSVGFEImageElement::OnStopDecode(imgIRequest *aRequest,
nsresult status,
const PRUnichar *statusArg)
{
nsresult rv =
nsImageLoadingContent::OnStopDecode(aRequest, status, statusArg);
Invalidate();
return rv;
}
NS_IMETHODIMP
nsSVGFEImageElement::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsRect * dirtyRect)
{
nsresult rv =
nsImageLoadingContent::FrameChanged(aContainer, newframe, dirtyRect);
Invalidate();
return rv;
}
NS_IMETHODIMP
nsSVGFEImageElement::OnStartContainer(imgIRequest *aRequest,
imgIContainer *aContainer)
{
nsresult rv =
nsImageLoadingContent::OnStartContainer(aRequest, aContainer);
Invalidate();
return rv;
}
//----------------------------------------------------------------------
// helper methods
void
nsSVGFEImageElement::Invalidate()
{
nsCOMPtr<nsIDOMSVGFilterElement> filter = do_QueryInterface(GetParent());
if (filter) {
static_cast<nsSVGFilterElement*>(GetParent())->Invalidate();
}
}
//---------------------UnimplementedMOZ------------------------
typedef nsSVGFE nsSVGFEUnimplementedMOZElementBase;

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

@ -301,6 +301,16 @@ interface nsIDOMSVGFESpotLightElement : nsIDOMSVGElement {
readonly attribute nsIDOMSVGAnimatedNumber limitingConeAngle;
};
[scriptable, uuid(3250f5c9-9c76-4e77-96d8-5f0cc85f41c4)]
interface nsIDOMSVGFEImageElement : nsIDOMSVGFilterPrimitiveStandardAttributes
/*
nsIDOMSVGURIReference,
nsIDOMSVGLangSpace,
nsIDOMSVGExternalResourcesRequired
*/
{
};
[scriptable, uuid(8698c635-26c7-468b-905e-494e8825d56b)]
interface nsIDOMSVGFEUnimplementedMOZElement : nsIDOMSVGFilterPrimitiveStandardAttributes
{

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

@ -259,6 +259,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_SVGFEFuncGElement_id,
eDOMClassInfo_SVGFEFuncRElement_id,
eDOMClassInfo_SVGFEGaussianBlurElement_id,
eDOMClassInfo_SVGFEImageElement_id,
eDOMClassInfo_SVGFEMergeElement_id,
eDOMClassInfo_SVGFEMergeNodeElement_id,
eDOMClassInfo_SVGFEMorphologyElement_id,

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

@ -944,6 +944,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEGaussianBlurElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEImageElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEMergeElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEMergeNodeElement, nsElementSH,
@ -2748,6 +2750,14 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEImageElement, nsIDOMSVGFEImageElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEMergeElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEMergeElement, nsIDOMSVGFEMergeElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEMergeElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)

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

@ -166,7 +166,8 @@ nsSVGPropertyBase::ContentRemoved(nsIDocument *aDocument,
DoUpdate();
}
class nsSVGFilterProperty : public nsSVGPropertyBase {
class nsSVGFilterProperty :
public nsSVGPropertyBase, public nsISVGFilterProperty {
public:
nsSVGFilterProperty(nsIContent *aFilter, nsIFrame *aFilteredFrame);
virtual ~nsSVGFilterProperty() {
@ -177,9 +178,15 @@ public:
nsSVGFilterFrame *GetFilterFrame();
void UpdateRect();
// nsISupports
NS_DECL_ISUPPORTS
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
// nsISVGFilterProperty
virtual void Invalidate() { DoUpdate(); }
private:
// nsSVGPropertyBase
virtual void DoUpdate();
@ -187,6 +194,10 @@ private:
nsRect mFilterRect;
};
NS_IMPL_ISUPPORTS_INHERITED1(nsSVGFilterProperty,
nsSVGPropertyBase,
nsISVGFilterProperty)
nsSVGFilterProperty::nsSVGFilterProperty(nsIContent *aFilter,
nsIFrame *aFilteredFrame)
: nsSVGPropertyBase(aFilter, aFilteredFrame, nsGkAtoms::filter)

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

@ -166,6 +166,19 @@ private:
nsSVGRenderState::RenderMode mOriginalMode;
};
#define NS_ISVGFILTERPROPERTY_IID \
{ 0x9744ee20, 0x1bcf, 0x4c62, \
{ 0x86, 0x7d, 0xd3, 0x7a, 0x91, 0x60, 0x3e, 0xef } }
class nsISVGFilterProperty : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGFILTERPROPERTY_IID)
virtual void Invalidate() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGFilterProperty, NS_ISVGFILTERPROPERTY_IID)
class nsSVGUtils
{
public: