From 4a3e054bee8258725ae32a8bcb4b06088682f267 Mon Sep 17 00:00:00 2001 From: "tor%cs.brown.edu" Date: Tue, 6 Sep 2005 22:30:40 +0000 Subject: [PATCH] Bug 301234 - implement subset of SVG filters. r=scooter git-svn-id: svn://10.0.0.236/trunk@179732 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/svg/content/src/Makefile.in | 4 + .../content/svg/content/src/nsISVGFilter.h | 65 + .../svg/content/src/nsSVGAnimatedInteger.cpp | 212 ++ .../svg/content/src/nsSVGAnimatedInteger.h | 52 + .../content/svg/content/src/nsSVGAtomList.h | 39 +- .../svg/content/src/nsSVGElementFactory.cpp | 56 +- .../svg/content/src/nsSVGFilterElement.cpp | 387 ++++ .../content/svg/content/src/nsSVGFilters.cpp | 2038 +++++++++++++++++ .../svg/content/src/nsSVGGraphicElement.cpp | 4 +- .../svg/content/src/nsSVGSVGElement.cpp | 4 +- mozilla/dom/public/idl/svg/Makefile.in | 3 + .../idl/svg/nsIDOMSVGAnimatedInteger.idl | 61 + .../public/idl/svg/nsIDOMSVGFilterElement.idl | 79 + .../dom/public/idl/svg/nsIDOMSVGFilters.idl | 136 ++ mozilla/dom/public/nsIDOMClassInfo.h | 12 + mozilla/dom/src/base/nsDOMClassInfo.cpp | 102 + mozilla/layout/base/nsCSSFrameConstructor.cpp | 5 + mozilla/layout/base/nsLayoutAtomList.h | 1 + mozilla/layout/style/nsCSSParser.cpp | 2 + mozilla/layout/style/nsCSSPropList.h | 1 + mozilla/layout/style/nsCSSStruct.cpp | 2 + mozilla/layout/style/nsCSSStruct.h | 1 + mozilla/layout/style/nsRuleNode.cpp | 9 + mozilla/layout/style/nsStyleContext.cpp | 3 +- mozilla/layout/style/nsStyleStruct.cpp | 3 + mozilla/layout/style/nsStyleStruct.h | 3 + mozilla/layout/svg/base/src/Makefile.in | 6 +- .../layout/svg/base/src/nsISVGChildFrame.h | 24 +- .../svg/base/src/nsSVGClipPathFrame.cpp | 4 +- .../layout/svg/base/src/nsSVGDefsFrame.cpp | 10 +- mozilla/layout/svg/base/src/nsSVGDefsFrame.h | 11 +- .../layout/svg/base/src/nsSVGFilterFrame.cpp | 743 ++++++ .../layout/svg/base/src/nsSVGFilterFrame.h | 68 + .../layout/svg/base/src/nsSVGFilterInstance.h | 99 + .../svg/base/src/nsSVGForeignObjectFrame.cpp | 32 +- mozilla/layout/svg/base/src/nsSVGGFrame.cpp | 103 +- mozilla/layout/svg/base/src/nsSVGGFrame.h | 27 +- .../base/src/nsSVGGenericContainerFrame.cpp | 10 +- .../svg/base/src/nsSVGGenericContainerFrame.h | 11 +- .../layout/svg/base/src/nsSVGGlyphFrame.cpp | 59 +- .../svg/base/src/nsSVGGradientFrame.cpp | 4 +- .../layout/svg/base/src/nsSVGImageFrame.cpp | 31 +- .../svg/base/src/nsSVGInnerSVGFrame.cpp | 126 +- .../layout/svg/base/src/nsSVGMarkerFrame.cpp | 6 +- .../svg/base/src/nsSVGOuterSVGFrame.cpp | 4 +- .../svg/base/src/nsSVGPathGeometryFrame.cpp | 116 +- .../svg/base/src/nsSVGPathGeometryFrame.h | 19 +- .../layout/svg/base/src/nsSVGTSpanFrame.cpp | 26 +- mozilla/layout/svg/base/src/nsSVGTSpanFrame.h | 12 +- .../layout/svg/base/src/nsSVGTextFrame.cpp | 112 +- mozilla/layout/svg/base/src/nsSVGUseFrame.cpp | 7 +- mozilla/layout/svg/base/src/nsSVGUtils.cpp | 114 + mozilla/layout/svg/base/src/nsSVGUtils.h | 36 + 53 files changed, 4972 insertions(+), 132 deletions(-) create mode 100644 mozilla/content/svg/content/src/nsISVGFilter.h create mode 100644 mozilla/content/svg/content/src/nsSVGAnimatedInteger.cpp create mode 100644 mozilla/content/svg/content/src/nsSVGAnimatedInteger.h create mode 100644 mozilla/content/svg/content/src/nsSVGFilterElement.cpp create mode 100644 mozilla/content/svg/content/src/nsSVGFilters.cpp create mode 100644 mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedInteger.idl create mode 100644 mozilla/dom/public/idl/svg/nsIDOMSVGFilterElement.idl create mode 100644 mozilla/dom/public/idl/svg/nsIDOMSVGFilters.idl create mode 100644 mozilla/layout/svg/base/src/nsSVGFilterFrame.cpp create mode 100644 mozilla/layout/svg/base/src/nsSVGFilterFrame.h create mode 100644 mozilla/layout/svg/base/src/nsSVGFilterInstance.h diff --git a/mozilla/content/svg/content/src/Makefile.in b/mozilla/content/svg/content/src/Makefile.in index da8950c6088..3e48f4d5cc7 100644 --- a/mozilla/content/svg/content/src/Makefile.in +++ b/mozilla/content/svg/content/src/Makefile.in @@ -71,6 +71,7 @@ CPPSRCS = \ nsSVGAngle.cpp \ nsSVGAnimatedAngle.cpp \ nsSVGAnimatedEnumeration.cpp \ + nsSVGAnimatedInteger.cpp \ nsSVGAnimatedLength.cpp \ nsSVGAnimatedLengthList.cpp \ nsSVGAnimatedNumber.cpp \ @@ -91,6 +92,8 @@ CPPSRCS = \ nsSVGEllipseElement.cpp \ nsSVGEnum.cpp \ nsSVGFeatures.cpp \ + nsSVGFilterElement.cpp \ + nsSVGFilters.cpp \ nsSVGGElement.cpp \ nsSVGGenericStringValue.cpp \ nsSVGGradientElement.cpp \ @@ -144,6 +147,7 @@ FORCE_STATIC_LIB = 1 EXPORTS = \ nsIDOMSVGListener.h \ nsIDOMSVGZoomListener.h \ + nsISVGFilter.h \ nsISVGTextContentMetrics.h \ nsISVGValue.h \ nsISVGValueObserver.h \ diff --git a/mozilla/content/svg/content/src/nsISVGFilter.h b/mozilla/content/svg/content/src/nsISVGFilter.h new file mode 100644 index 00000000000..f7b5df16a43 --- /dev/null +++ b/mozilla/content/svg/content/src/nsISVGFilter.h @@ -0,0 +1,65 @@ +/* -*- 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): + * + * 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 ***** */ + +#ifndef __NS_ISVGFILTER_H__ +#define __NS_ISVGFILTER_H__ + +#define NS_ISVGFILTER_IID \ +{ 0xbc1bf81a, 0x9765, 0x43c0, { 0xb3, 0x17, 0xd6, 0x91, 0x66, 0xcd, 0x3a, 0x30 } } + +// Bitfields used by nsISVGFilter::GetRequirements() +#define NS_FE_SOURCEGRAPHIC 0x01 +#define NS_FE_SOURCEALPHA 0x02 +#define NS_FE_BACKGROUNDIMAGE 0x04 +#define NS_FE_BACKGROUNDALPHA 0x08 +#define NS_FE_FILLPAINT 0x10 +#define NS_FE_STROKEPAINT 0x20 + +class nsSVGFilterInstance; + +class nsISVGFilter : public nsISupports { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISVGFILTER_IID) + + // Perform the filter operation on the images/regions + // specified by 'instance' + NS_IMETHOD Filter(nsSVGFilterInstance *instance) = 0; + + // Get the standard image source requirements of this filter. + NS_IMETHOD GetRequirements(PRUint32 *aRequirements) = 0; +}; + +#endif diff --git a/mozilla/content/svg/content/src/nsSVGAnimatedInteger.cpp b/mozilla/content/svg/content/src/nsSVGAnimatedInteger.cpp new file mode 100644 index 00000000000..16bd97b02ef --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGAnimatedInteger.cpp @@ -0,0 +1,212 @@ +/* -*- 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. + * + * Parts of this file contain code derived from the following files(s) + * of the Mozilla SVG project (these parts are Copyright (C) by their + * respective copyright-holders): + * content/svg/content/src/nsSVGAnimatedNumber.cpp + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 NPL, 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 "nsSVGAnimatedInteger.h" +#include "nsTextFormatter.h" +#include "prdtoa.h" +#include "nsSVGValue.h" +#include "nsISVGValueUtils.h" +#include "nsDOMError.h" +#include "nsContentUtils.h" + +//////////////////////////////////////////////////////////////////////// +// nsSVGAnimatedInteger + +class nsSVGAnimatedInteger : public nsIDOMSVGAnimatedInteger, + public nsSVGValue +{ +protected: + friend nsresult NS_NewSVGAnimatedInteger(nsIDOMSVGAnimatedInteger** result, + PRInt32 aBaseVal); + nsSVGAnimatedInteger(); + ~nsSVGAnimatedInteger(); + void Init(PRInt32 aBaseVal); + +public: + // nsISupports interface: + NS_DECL_ISUPPORTS + + // nsIDOMSVGAnimatedInteger interface: + NS_DECL_NSIDOMSVGANIMATEDINTEGER + + // remainder of nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString& aValue); + NS_IMETHOD GetValueString(nsAString& aValue); + +protected: + PRInt32 mBaseVal; +}; + + + +//---------------------------------------------------------------------- +// Implementation + +nsSVGAnimatedInteger::nsSVGAnimatedInteger() +{ +} + +nsSVGAnimatedInteger::~nsSVGAnimatedInteger() +{ +} + +void +nsSVGAnimatedInteger::Init(PRInt32 aBaseVal) +{ + mBaseVal = aBaseVal; +} + +//---------------------------------------------------------------------- +// nsISupports methods: + +NS_IMPL_ADDREF(nsSVGAnimatedInteger) +NS_IMPL_RELEASE(nsSVGAnimatedInteger) + + +NS_INTERFACE_MAP_BEGIN(nsSVGAnimatedInteger) + NS_INTERFACE_MAP_ENTRY(nsISVGValue) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedInteger) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedInteger) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue) +NS_INTERFACE_MAP_END + +//---------------------------------------------------------------------- +// nsISVGValue methods: + +NS_IMETHODIMP +nsSVGAnimatedInteger::SetValueString(const nsAString& aValue) +{ + nsresult rv = NS_OK; + WillModify(); + + char *str = ToNewCString(aValue); + + if (*str) { + char *tmp = str; + + // check if string is well formed + + if (*tmp != '-' && + *tmp != '+' && + !isdigit(*tmp)) + rv = NS_ERROR_FAILURE; + + tmp++; + + while (*tmp) { + if (!isdigit(*str)) { + rv = NS_ERROR_FAILURE; + break; + } + } + + if (NS_SUCCEEDED(rv)) + sscanf(str, "%d", &mBaseVal); + } + nsMemory::Free(str); + DidModify(); + return rv; +} + +NS_IMETHODIMP +nsSVGAnimatedInteger::GetValueString(nsAString& aValue) +{ + aValue.Truncate(); + + PRUnichar buf[24]; + nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar), + NS_LITERAL_STRING("%d").get(), + mBaseVal); + aValue.Append(buf); + + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIDOMSVGAnimatedInteger methods: + +/* attribute nsIDOMSVGNumber baseVal; */ +NS_IMETHODIMP +nsSVGAnimatedInteger::GetBaseVal(PRInt32 *aBaseVal) +{ + *aBaseVal = mBaseVal; + return NS_OK; +} + +/* attribute nsIDOMSVGNumber baseVal; */ +NS_IMETHODIMP +nsSVGAnimatedInteger::SetBaseVal(PRInt32 aBaseVal) +{ + WillModify(); + mBaseVal = aBaseVal; + DidModify(); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGNumber animVal; */ +NS_IMETHODIMP +nsSVGAnimatedInteger::GetAnimVal(PRInt32 *aAnimVal) +{ + *aAnimVal = mBaseVal; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// Exported creation functions + +nsresult +NS_NewSVGAnimatedInteger(nsIDOMSVGAnimatedInteger** aResult, + PRInt32 aBaseVal) +{ + *aResult = nsnull; + + nsSVGAnimatedInteger* animatedNumber = new nsSVGAnimatedInteger(); + if (!animatedNumber) return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(animatedNumber); + + animatedNumber->Init(aBaseVal); + + *aResult = (nsIDOMSVGAnimatedInteger*) animatedNumber; + + return NS_OK; +} + + diff --git a/mozilla/content/svg/content/src/nsSVGAnimatedInteger.h b/mozilla/content/svg/content/src/nsSVGAnimatedInteger.h new file mode 100644 index 00000000000..acb0af21ebb --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGAnimatedInteger.h @@ -0,0 +1,52 @@ +/* -*- 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. + * + * Parts of this file contain code derived from the following files(s) + * of the Mozilla SVG project (these parts are Copyright (C) by their + * respective copyright-holders): + * content/svg/content/src/nsSVGAnimatedNumber.h + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 NPL, 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 ----- */ + +#ifndef __NS_SVGANIMATEDINTEGER_H__ +#define __NS_SVGANIMATEDINTEGER_H__ + +#include "nsIDOMSVGAnimatedInteger.h" + +nsresult NS_NewSVGAnimatedInteger(nsIDOMSVGAnimatedInteger** result, + PRInt32 baseVal); + +#endif //__NS_SVGANIMATEDINTEGER_H__ + + diff --git a/mozilla/content/svg/content/src/nsSVGAtomList.h b/mozilla/content/svg/content/src/nsSVGAtomList.h index 0fd4e51c1f1..d6c93976181 100644 --- a/mozilla/content/svg/content/src/nsSVGAtomList.h +++ b/mozilla/content/svg/content/src/nsSVGAtomList.h @@ -60,6 +60,28 @@ SVG_ATOM(clipPath, "clipPath") SVG_ATOM(defs, "defs") SVG_ATOM(desc, "desc") SVG_ATOM(ellipse, "ellipse") +SVG_ATOM(feBlend, "feBlend") +SVG_ATOM(feColorMatrix, "feColorMatrix") +SVG_ATOM(feComponentTransfer, "feComponentTransfer") +SVG_ATOM(feComposite, "feComposite") +SVG_ATOM(feConvolveMatrix, "feConvolveMatrix") +SVG_ATOM(feDiffuseLighting, "feDiffuseLighting") +SVG_ATOM(feDisplacementMap, "feDisplacementMap") +SVG_ATOM(feFlood, "feFlood") +SVG_ATOM(feFuncR, "feFuncR") +SVG_ATOM(feFuncG, "feFuncG") +SVG_ATOM(feFuncB, "feFuncB") +SVG_ATOM(feFuncA, "feFuncA") +SVG_ATOM(feGaussianBlur, "feGaussianBlur") +SVG_ATOM(feImage, "feImage") +SVG_ATOM(feMerge, "feMerge") +SVG_ATOM(feMergeNode, "feMergeNode") +SVG_ATOM(feMorphology, "feMorphology") +SVG_ATOM(feOffset, "feOffset") +SVG_ATOM(feSpecularLighting, "feSpecularLighting") +SVG_ATOM(feTile, "feTile") +SVG_ATOM(feTurbulence, "feTurbulence") +SVG_ATOM(filter, "filter") #ifdef MOZ_SVG_FOREIGNOBJECT SVG_ATOM(foreignObject, "foreignObject") #endif @@ -91,6 +113,7 @@ SVG_ATOM(use, "use") // properties and attributes SVG_ATOM(alignment_baseline, "alignment-baseline") SVG_ATOM(align, "align") +SVG_ATOM(amplitude, "amplitude") SVG_ATOM(_auto, "auto") SVG_ATOM(baseline_shift, "baseline-shift") SVG_ATOM(_class, "class") @@ -104,15 +127,19 @@ SVG_ATOM(cx, "cx") SVG_ATOM(cy, "cy") SVG_ATOM(d, "d") SVG_ATOM(direction, "direction") +SVG_ATOM(discrete, "discrete") SVG_ATOM(display, "display") SVG_ATOM(dominant_baseline, "dominant-baseline") SVG_ATOM(dx, "dx") SVG_ATOM(dy, "dy") SVG_ATOM(exact, "exact") +SVG_ATOM(exponent, "exponent") SVG_ATOM(fill, "fill") SVG_ATOM(fill_opacity, "fill-opacity") SVG_ATOM(fill_rule, "fill-rule") -SVG_ATOM(filter, "filter") +// defined above - SVG_ATOM(filter, "filter") +SVG_ATOM(filterRes, "filterRes") +SVG_ATOM(filterUnits, "filterUnits") SVG_ATOM(font_family, "font-family") SVG_ATOM(font_size, "font-size") SVG_ATOM(font_size_adjust, "font-size-adjust") @@ -122,6 +149,7 @@ SVG_ATOM(font_variant, "font-variant") SVG_ATOM(font_weight, "font-weight") SVG_ATOM(fx, "fx") SVG_ATOM(fy, "fy") +SVG_ATOM(gamma, "gamma") SVG_ATOM(glyph_orientation_horizontal, "glyph-orientation-horizontal") SVG_ATOM(glyph_orientation_vertical, "glyph-orientation-vertical") SVG_ATOM(gradientUnits, "gradientUnits") @@ -129,9 +157,12 @@ SVG_ATOM(gradientTransform, "gradientTransform") SVG_ATOM(height, "height") SVG_ATOM(href, "href") SVG_ATOM(id, "id") +SVG_ATOM(identity, "identity") SVG_ATOM(image_rendering, "image-rendering") +SVG_ATOM(intercept, "intercept") SVG_ATOM(kerning, "kerning") SVG_ATOM(letter_spacing, "letter-spacing") +SVG_ATOM(linear, "linear") // defined above - SVG_ATOM(marker, "marker") SVG_ATOM(marker_end, "marker-end") SVG_ATOM(marker_mid, "marker-mid") @@ -163,17 +194,21 @@ SVG_ATOM(pathLength, "pathLength") SVG_ATOM(pointer_events, "pointer-events") SVG_ATOM(points, "points") SVG_ATOM(preserveAspectRatio, "preserveAspectRatio") +SVG_ATOM(primitiveUnits, "primitiveUnits") SVG_ATOM(r, "r") SVG_ATOM(refX, "refX") SVG_ATOM(refY, "refY") SVG_ATOM(requiredExtensions, "requiredExtensions") SVG_ATOM(requiredFeatures, "requiredFeatures") +SVG_ATOM(result, "result") SVG_ATOM(rx, "rx") SVG_ATOM(ry, "ry") SVG_ATOM(shape_rendering, "shape-rendering") +SVG_ATOM(slope, "slope") SVG_ATOM(space, "space") SVG_ATOM(spacing, "spacing") SVG_ATOM(spreadMethod, "spreadMethod") +SVG_ATOM(stdDeviation, "stdDeviation") SVG_ATOM(startOffset, "startOffset") SVG_ATOM(stop_color, "stop-color") SVG_ATOM(stop_opacity, "stop-opacity") @@ -189,6 +224,8 @@ SVG_ATOM(stroke_width, "stroke-width") SVG_ATOM(strokeWidth, "strokeWidth") SVG_ATOM(style, "style") SVG_ATOM(systemLanguage, "systemLanguage") +SVG_ATOM(table, "table") +SVG_ATOM(tableValues, "tableValues") SVG_ATOM(text_anchor, "text-anchor") SVG_ATOM(text_decoration, "text-decoration") SVG_ATOM(text_rendering, "text-rendering") diff --git a/mozilla/content/svg/content/src/nsSVGElementFactory.cpp b/mozilla/content/svg/content/src/nsSVGElementFactory.cpp index 6a9f58387b5..121afda680f 100644 --- a/mozilla/content/svg/content/src/nsSVGElementFactory.cpp +++ b/mozilla/content/svg/content/src/nsSVGElementFactory.cpp @@ -102,7 +102,28 @@ nsresult NS_NewSVGClipPathElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGTextPathElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); - +nsresult +NS_NewSVGFilterElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEGaussianBlurElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEComponentTransferElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEFuncRElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEFuncGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEFuncBElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEFuncAElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEMergeElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEMergeNodeElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEOffsetElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGFEUnimplementedMOZElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) @@ -175,6 +196,39 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) return NS_NewSVGClipPathElement(aResult, aNodeInfo); if (name == nsSVGAtoms::textPath) return NS_NewSVGTextPathElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::filter) + return NS_NewSVGFilterElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feGaussianBlur) + return NS_NewSVGFEGaussianBlurElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feComponentTransfer) + return NS_NewSVGFEComponentTransferElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feFuncR) + return NS_NewSVGFEFuncRElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feFuncG) + return NS_NewSVGFEFuncGElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feFuncB) + return NS_NewSVGFEFuncBElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feFuncA) + return NS_NewSVGFEFuncAElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feMerge) + return NS_NewSVGFEMergeElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feMergeNode) + return NS_NewSVGFEMergeNodeElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feOffset) + return NS_NewSVGFEOffsetElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::feBlend || + name == nsSVGAtoms::feColorMatrix || + name == nsSVGAtoms::feComposite || + name == nsSVGAtoms::feConvolveMatrix || + name == nsSVGAtoms::feDiffuseLighting || + name == nsSVGAtoms::feDisplacementMap || + name == nsSVGAtoms::feFlood || + name == nsSVGAtoms::feImage || + name == nsSVGAtoms::feMorphology || + name == nsSVGAtoms::feSpecularLighting || + name == nsSVGAtoms::feTile || + name == nsSVGAtoms::feTurbulence) + return NS_NewSVGFEUnimplementedMOZElement(aResult, aNodeInfo); // if we don't know what to create, just create a standard xml element: return NS_NewXMLElement(aResult, aNodeInfo); diff --git a/mozilla/content/svg/content/src/nsSVGFilterElement.cpp b/mozilla/content/svg/content/src/nsSVGFilterElement.cpp new file mode 100644 index 00000000000..8139df295aa --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGFilterElement.cpp @@ -0,0 +1,387 @@ +/* -*- 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): + * + * 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 "nsSVGGraphicElement.h" +#include "nsSVGAtoms.h" +#include "nsSVGAnimatedLength.h" +#include "nsSVGLength.h" +#include "nsIDOMSVGFilterElement.h" +#include "nsCOMPtr.h" +#include "nsISVGSVGElement.h" +#include "nsSVGCoordCtxProvider.h" +#include "nsSVGAnimatedEnumeration.h" +#include "nsSVGAnimatedInteger.h" +#include "nsSVGEnum.h" + +typedef nsSVGGraphicElement nsSVGFilterElementBase; + +class nsSVGFilterElement : public nsSVGFilterElementBase, + public nsIDOMSVGFilterElement, + public nsSVGValue +{ +protected: + friend nsresult NS_NewSVGFilterElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFilterElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGFilterElement(); + nsresult Init(); + + // nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString &aValue) { return NS_OK; } + NS_IMETHOD GetValueString(nsAString& aValue) { return NS_ERROR_NOT_IMPLEMENTED; } + +public: + // interfaces: + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGFILTERELEMENT + + // xxx I wish we could use virtual inheritance + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFilterElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFilterElementBase::) + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFilterElementBase::) + + // nsIContent + virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, + PRBool aNotify); + virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify); + +protected: + + nsCOMPtr mFilterUnits; + nsCOMPtr mPrimitiveUnits; + nsCOMPtr mX; + nsCOMPtr mY; + nsCOMPtr mWidth; + nsCOMPtr mHeight; + nsCOMPtr mFilterResX; + nsCOMPtr mFilterResY; +}; + + +NS_IMPL_NS_NEW_SVG_ELEMENT(Filter) + + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFilterElement,nsSVGFilterElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFilterElement,nsSVGFilterElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFilterElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterElement) + NS_INTERFACE_MAP_ENTRY(nsISVGValue) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFilterElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFilterElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFilterElement::nsSVGFilterElement(nsINodeInfo *aNodeInfo) + : nsSVGFilterElementBase(aNodeInfo) +{ + +} + +nsSVGFilterElement::~nsSVGFilterElement() +{ +} + + +nsresult +nsSVGFilterElement::Init() +{ + nsresult rv = nsSVGFilterElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // Define enumeration mappings + static struct nsSVGEnumMapping gUnitMap[] = { + {&nsSVGAtoms::objectBoundingBox, nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX}, + {&nsSVGAtoms::userSpaceOnUse, nsIDOMSVGFilterElement::SVG_FUNITS_USERSPACEONUSE}, + {nsnull, 0} + }; + + // Create mapped properties: + + // DOM property: filterUnits , #IMPLIED attrib: filterUnits + { + nsCOMPtr units; + rv = NS_NewSVGEnum(getter_AddRefs(units), + nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX, gUnitMap); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mFilterUnits), units); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::filterUnits, mFilterUnits); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: primitiveUnits , #IMPLIED attrib: primitiveUnits + { + nsCOMPtr units; + rv = NS_NewSVGEnum(getter_AddRefs(units), + nsIDOMSVGFilterElement::SVG_FUNITS_USERSPACEONUSE, gUnitMap); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mPrimitiveUnits), units); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::primitiveUnits, mPrimitiveUnits); + NS_ENSURE_SUCCESS(rv,rv); + } + + + // DOM property: x , #IMPLIED attrib: x + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + -10.0f, + nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mX), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::x, mX); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: y , #IMPLIED attrib: y + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + -10.0f, + nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mY), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::y, mY); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: width , #REQUIRED attrib: width + // XXX: enforce requiredness + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 120.0f, + nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mWidth), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::width, mWidth); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: height , #REQUIRED attrib: height + // XXX: enforce requiredness + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 120.0f, + nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mHeight), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::height, mHeight); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: filterResX , #IMPLIED attrib: filterRes + { + rv = NS_NewSVGAnimatedInteger(getter_AddRefs(mFilterResX), 0); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: filterResY , #IMPLIED attrib: filterRes + { + rv = NS_NewSVGAnimatedInteger(getter_AddRefs(mFilterResY), 0); + NS_ENSURE_SUCCESS(rv,rv); + } + + return rv; +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFilterElement) + + +//---------------------------------------------------------------------- +// nsIDOMSVGFilterElement methods + +/* readonly attribute nsIDOMSVGAnimatedLength x; */ +NS_IMETHODIMP nsSVGFilterElement::GetX(nsIDOMSVGAnimatedLength * *aX) +{ + *aX = mX; + NS_IF_ADDREF(*aX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength y; */ +NS_IMETHODIMP nsSVGFilterElement::GetY(nsIDOMSVGAnimatedLength * *aY) +{ + *aY = mY; + NS_IF_ADDREF(*aY); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength width; */ +NS_IMETHODIMP nsSVGFilterElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) +{ + *aWidth = mWidth; + NS_IF_ADDREF(*aWidth); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength height; */ +NS_IMETHODIMP nsSVGFilterElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) +{ + *aHeight = mHeight; + NS_IF_ADDREF(*aHeight); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration filterUnits; */ +NS_IMETHODIMP nsSVGFilterElement::GetFilterUnits(nsIDOMSVGAnimatedEnumeration * *aUnits) +{ + *aUnits = mFilterUnits; + NS_IF_ADDREF(*aUnits); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration primitiveUnits; */ +NS_IMETHODIMP nsSVGFilterElement::GetPrimitiveUnits(nsIDOMSVGAnimatedEnumeration * *aUnits) +{ + *aUnits = mPrimitiveUnits; + NS_IF_ADDREF(*aUnits); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration filterResY; */ +NS_IMETHODIMP nsSVGFilterElement::GetFilterResX(nsIDOMSVGAnimatedInteger * *aFilterResX) +{ + *aFilterResX = mFilterResX; + NS_IF_ADDREF(*aFilterResX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration filterResY; */ +NS_IMETHODIMP nsSVGFilterElement::GetFilterResY(nsIDOMSVGAnimatedInteger * *aFilterResY) +{ + *aFilterResY = mFilterResY; + NS_IF_ADDREF(*aFilterResY); + return NS_OK; +} + +/* void setFilterRes (in unsigned long filterResX, in unsigned long filterResY); + */ +NS_IMETHODIMP +nsSVGFilterElement::SetFilterRes(PRUint32 filterResX, PRUint32 filterResY) +{ + mFilterResX->SetBaseVal(filterResX); + mFilterResY->SetBaseVal(filterResY); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIContent methods + +nsresult +nsSVGFilterElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, + PRBool aNotify) +{ + WillModify(); + nsresult rv = nsSVGFilterElementBase::InsertChildAt(aKid, aIndex, aNotify); + DidModify(); + + return rv; +} + +nsresult +nsSVGFilterElement::AppendChildTo(nsIContent* aKid, PRBool aNotify) +{ + WillModify(); + nsresult rv = nsSVGFilterElementBase::AppendChildTo(aKid, aNotify); + DidModify(); + + return rv; +} + +nsresult +nsSVGFilterElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +{ + WillModify(); + nsresult rv = nsSVGFilterElementBase::RemoveChildAt(aIndex, aNotify); + DidModify(); + + return rv; +} + +nsresult +nsSVGFilterElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify) +{ + nsresult rv = nsSVGFilterElementBase::SetAttr(aNameSpaceID, aName, aPrefix, + aValue, aNotify); + + if (aName == nsSVGAtoms::filterRes && aNameSpaceID == kNameSpaceID_None) { + PRUint32 resX, resY; + char *str; + str = ToNewCString(aValue); + int num = sscanf(str, "%d %d\n", &resX, &resY); + switch (num) { + case 2: + mFilterResX->SetBaseVal(resX); + mFilterResY->SetBaseVal(resY); + break; + case 1: + mFilterResX->SetBaseVal(resX); + mFilterResY->SetBaseVal(resX); + break; + default: + break; + } + nsMemory::Free(str); + } + + return rv; +} diff --git a/mozilla/content/svg/content/src/nsSVGFilters.cpp b/mozilla/content/svg/content/src/nsSVGFilters.cpp new file mode 100644 index 00000000000..01fcb8194a8 --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGFilters.cpp @@ -0,0 +1,2038 @@ +/* -*- 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): + * + * 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 "nsSVGElement.h" +#include "nsSVGAnimatedLength.h" +#include "nsSVGAnimatedNumber.h" +#include "nsSVGAnimatedString.h" +#include "nsSVGLength.h" +#include "nsSVGNumber.h" +#include "nsSVGAtoms.h" +#include "nsIDOMSVGFilters.h" +#include "nsCOMPtr.h" +#include "nsSVGStylableElement.h" +#include "nsISVGFilter.h" +#include "nsSVGFilterInstance.h" +#include "nsSVGValue.h" +#include "nsISVGValueObserver.h" +#include "nsWeakReference.h" +#include "nsIDOMSVGFilterElement.h" +#include "nsSVGEnum.h" +#include "nsSVGAnimatedEnumeration.h" +#include "nsSVGNumberList.h" +#include "nsSVGAnimatedNumberList.h" +#include "nsSVGNumber.h" +#include "nsSVGAnimatedNumber.h" +#include "nsISVGValueUtils.h" + +typedef nsSVGStylableElement nsSVGFEBase; + +class nsSVGFE : public nsSVGFEBase +//, public nsIDOMSVGFilterPrimitiveStandardAttributes +{ +protected: + nsSVGFE(nsINodeInfo *aNodeInfo); + nsresult Init(); + + // nsISVGValueObserver interface: + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType); + +public: + // interfaces: + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES + +protected: + + // nsIDOMSVGFitlerPrimitiveStandardAttributes values + nsCOMPtr mX; + nsCOMPtr mY; + nsCOMPtr mWidth; + nsCOMPtr mHeight; + nsCOMPtr mResult; +}; + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFE) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFE::nsSVGFE(nsINodeInfo* aNodeInfo) : nsSVGFEBase(aNodeInfo) +{ +} + +nsresult +nsSVGFE::Init() +{ + nsresult rv = nsSVGFEBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // DOM property: x , #IMPLIED attrib: x + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 0.0f, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mX), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::x, mX); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: y , #IMPLIED attrib: y + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 0.0f, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mY), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::y, mY); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: width , #REQUIRED attrib: width + // XXX: enforce requiredness + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 100.0f, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mWidth), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::width, mWidth); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: height , #REQUIRED attrib: height + // XXX: enforce requiredness + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 100.0f, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mHeight), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::height, mHeight); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: result , #REQUIRED attrib: result + { + rv = NS_NewSVGAnimatedString(getter_AddRefs(mResult)); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::result, mResult); + NS_ENSURE_SUCCESS(rv,rv); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFE::WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + return nsSVGFEBase::WillModifySVGObservable(observable, aModType); +} + +NS_IMETHODIMP +nsSVGFE::DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->EndBatchUpdate(); + return nsSVGFEBase::DidModifySVGObservable(observable, aModType); +} + + +//---------------------------------------------------------------------- +// nsIDOMSVGFilterPrimitiveStandardAttributes methods + +/* readonly attribute nsIDOMSVGAnimatedLength x; */ +NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX) +{ + *aX = mX; + NS_IF_ADDREF(*aX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength y; */ +NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY) +{ + *aY = mY; + NS_IF_ADDREF(*aY); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength width; */ +NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) +{ + *aWidth = mWidth; + NS_IF_ADDREF(*aWidth); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength height; */ +NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) +{ + *aHeight = mHeight; + NS_IF_ADDREF(*aHeight); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedString result; */ +NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult) +{ + *aResult = mResult; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + +//---------------------Gaussian Blur------------------------ + +typedef nsSVGFE nsSVGFEGaussianBlurElementBase; + +class nsSVGFEGaussianBlurElement : public nsSVGFEGaussianBlurElementBase, + public nsIDOMSVGFEGaussianBlurElement, + public nsISVGFilter +{ +protected: + friend nsresult NS_NewSVGFEGaussianBlurElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEGaussianBlurElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGFEGaussianBlurElement(); + nsresult Init(); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + // FE Base + NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEGaussianBlurElementBase::) + + // nsISVGFilter + NS_IMETHOD Filter(nsSVGFilterInstance *instance); + NS_IMETHOD GetRequirements(PRUint32 *aRequirements); + + // Gaussian + NS_DECL_NSIDOMSVGFEGAUSSIANBLURELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEGaussianBlurElementBase::) + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFEGaussianBlurElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFEGaussianBlurElementBase::) + + virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify); + +protected: + + nsCOMPtr mStdDeviationX; + nsCOMPtr mStdDeviationY; + nsCOMPtr mIn1; +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEGaussianBlur) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFEGaussianBlurElement,nsSVGFEGaussianBlurElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFEGaussianBlurElement,nsSVGFEGaussianBlurElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEGaussianBlurElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEGaussianBlurElement) + NS_INTERFACE_MAP_ENTRY(nsISVGFilter) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEGaussianBlurElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEGaussianBlurElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFEGaussianBlurElement::nsSVGFEGaussianBlurElement(nsINodeInfo *aNodeInfo) + : nsSVGFEGaussianBlurElementBase(aNodeInfo) +{ +} + +nsSVGFEGaussianBlurElement::~nsSVGFEGaussianBlurElement() +{ + NS_REMOVE_SVGVALUE_OBSERVER(mStdDeviationX); + NS_REMOVE_SVGVALUE_OBSERVER(mStdDeviationY); +} + +nsresult +nsSVGFEGaussianBlurElement::Init() +{ + nsresult rv = nsSVGFEGaussianBlurElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // DOM property: in1 , #IMPLIED attrib: in + { + rv = NS_NewSVGAnimatedString(getter_AddRefs(mIn1)); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::in, mIn1); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: stdDeviationX , #IMPLIED attrib: mStdDeviation + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mStdDeviationX), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: stdDeviationY , #IMPLIED attrib: mStdDeviation + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mStdDeviationY), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + } + + // add observers -------------------------- : + NS_ADD_SVGVALUE_OBSERVER(mStdDeviationX); + NS_ADD_SVGVALUE_OBSERVER(mStdDeviationY); + + return rv; +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEGaussianBlurElement) + + +//---------------------------------------------------------------------- +// nsIDOMSVGFEGaussianBlurElement methods + +/* readonly attribute nsIDOMSVGAnimatedString in1; */ +NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) +{ + *aIn = mIn1; + NS_IF_ADDREF(*aIn); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber stdDeviationX; */ +NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetStdDeviationX(nsIDOMSVGAnimatedNumber * *aX) +{ + *aX = mStdDeviationX; + NS_IF_ADDREF(*aX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber stdDeviationY; */ +NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetStdDeviationY(nsIDOMSVGAnimatedNumber * *aY) +{ + *aY = mStdDeviationY; + NS_IF_ADDREF(*aY); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFEGaussianBlurElement::SetStdDeviation(float stdDeviationX, float stdDeviationY) +{ + mStdDeviationX->SetBaseVal(stdDeviationX); + mStdDeviationY->SetBaseVal(stdDeviationY); + return NS_OK; +} + +nsresult +nsSVGFEGaussianBlurElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify) +{ + nsresult rv = nsSVGFEGaussianBlurElementBase::SetAttr(aNameSpaceID, aName, aPrefix, + aValue, aNotify); + + if (aName == nsSVGAtoms::stdDeviation && aNameSpaceID == kNameSpaceID_None) { + float stdX = 0.0f, stdY = 0.0f; + char *str; + str = ToNewCString(aValue); + int num = sscanf(str, "%f %f\n", &stdX, &stdY); + if (num == 1) + stdY = stdX; + mStdDeviationX->SetBaseVal(stdX); + mStdDeviationY->SetBaseVal(stdY); + nsMemory::Free(str); + } + + return rv; +} + +static void +boxBlurH(PRUint8 *aInput, PRUint8 *aOutput, + PRInt32 aStride, nsRect aRegion, + PRUint32 leftLobe, PRUint32 rightLobe) +{ + PRUint32 boxSize = leftLobe + rightLobe + 1; + + for (PRInt32 y = aRegion.y; y < aRegion.y + aRegion.height; y++) + for (PRInt32 x = aRegion.x; x < aRegion.x + aRegion.width; x++) { + PRUint32 sums[4] = {0, 0, 0, 0}; + for (PRUint32 i=0; i < boxSize; i++) { + PRInt32 pos = (int)x - leftLobe + i; + pos = PR_MAX(pos, aRegion.x); + pos = PR_MIN(pos, aRegion.x + aRegion.width - 1); + sums[0] += aInput[aStride*y + 4*pos ]; + sums[1] += aInput[aStride*y + 4*pos + 1]; + sums[2] += aInput[aStride*y + 4*pos + 2]; + sums[3] += aInput[aStride*y + 4*pos + 3]; + } + aOutput[aStride*y + 4*x ] = sums[0]/boxSize; + aOutput[aStride*y + 4*x + 1] = sums[1]/boxSize; + aOutput[aStride*y + 4*x + 2] = sums[2]/boxSize; + aOutput[aStride*y + 4*x + 3] = sums[3]/boxSize; + } +} + +static void +boxBlurV(PRUint8 *aInput, PRUint8 *aOutput, + PRInt32 aStride, nsRect aRegion, + unsigned topLobe, unsigned bottomLobe) +{ + PRUint32 boxSize = topLobe + bottomLobe + 1; + + for (PRInt32 y = aRegion.y; y < aRegion.y + aRegion.height; y++) + for (PRInt32 x = aRegion.x; x < aRegion.x + aRegion.width; x++) { + PRUint32 sums[4] = {0, 0, 0, 0}; + for (PRUint32 i = 0; i < boxSize; i++) { + PRInt32 pos = (int)y - topLobe + i; + pos = PR_MAX(pos, aRegion.y); + pos = PR_MIN(pos, aRegion.y + aRegion.height - 1); + sums[0] += aInput[aStride*pos + 4*x ]; + sums[1] += aInput[aStride*pos + 4*x + 1]; + sums[2] += aInput[aStride*pos + 4*x + 2]; + sums[3] += aInput[aStride*pos + 4*x + 3]; + } + aOutput[aStride*y + 4*x ] = sums[0]/boxSize; + aOutput[aStride*y + 4*x + 1] = sums[1]/boxSize; + aOutput[aStride*y + 4*x + 2] = sums[2]/boxSize; + aOutput[aStride*y + 4*x + 3] = sums[3]/boxSize; + } +} + +#ifndef M_PI +#define M_PI 3.1415926 +#endif + +static void +gaussianBlur(PRUint8 *aInput, PRUint8 *aOutput, + PRUint32 aLength, PRInt32 aStride, nsRect aRegion, + float aStdX, float aStdY) +{ + PRUint32 dX, dY; + dX = (PRUint32) floor(aStdX * 3*sqrt(2*M_PI)/4 + 0.5); + dY = (PRUint32) floor(aStdY * 3*sqrt(2*M_PI)/4 + 0.5); + + PRUint8 *tmp = new PRUint8[aLength]; + + if (dX & 1) { + // odd + boxBlurH(aInput, tmp, aStride, aRegion, dX/2, dX/2); + boxBlurH(tmp, aOutput, aStride, aRegion, dX/2, dX/2); + boxBlurH(aOutput, tmp, aStride, aRegion, dX/2, dX/2); + } else { + // even + boxBlurH(aInput, tmp, aStride, aRegion, dX/2, dX/2 - 1); + boxBlurH(tmp, aOutput, aStride, aRegion, dX/2 - 1, dX/2); + boxBlurH(aOutput, tmp, aStride, aRegion, dX/2, dX/2); + } + + if (dY & 1) { + // odd + boxBlurV(tmp, aOutput, aStride, aRegion, dY/2, dY/2); + boxBlurV(aOutput, tmp, aStride, aRegion, dY/2, dY/2); + boxBlurV(tmp, aOutput, aStride, aRegion, dY/2, dY/2); + } else { + // even + boxBlurV(tmp, aOutput, aStride, aRegion, dY/2, dY/2 - 1); + boxBlurV(aOutput, tmp, aStride, aRegion, dY/2 - 1, dY/2); + boxBlurV(tmp, aOutput, aStride, aRegion, dY/2, dY/2); + } + + delete [] tmp; +} + +static void +fixupTarget(PRUint8 *aSource, PRUint8 *aTarget, + PRUint32 aWidth, PRUint32 aHeight, + PRInt32 aStride, nsRect aRegion) +{ + // top + if (aRegion.y > 0) + for (PRInt32 y = 0; y < aRegion.y; y++) + if (aSource) + memcpy(aTarget + y * aStride, aSource + y * aStride, aStride); + else + memset(aTarget + y * aStride, 0, aStride); + + // bottom + if (aRegion.y + aRegion.height < aHeight) + for (PRInt32 y = aRegion.y + aRegion.height; y < aHeight; y++) + if (aSource) + memcpy(aTarget + y * aStride, aSource + y * aStride, aStride); + else + memset(aTarget + y * aStride, 0, aStride); + + // left + if (aRegion.x > 0) + for (PRInt32 y = aRegion.y; y < aRegion.y + aRegion.height; y++) + memcpy(aTarget + y * aStride, aSource + y * aStride, 4 * aRegion.x); + + // right + if (aRegion.x + aRegion.width < aWidth) + for (PRInt32 y = aRegion.y; y < aRegion.y + aRegion.height; y++) + if (aSource) + memcpy(aTarget + y * aStride + 4 * (aRegion.x + aRegion.width), + aSource + y * aStride + 4 * (aRegion.x + aRegion.width), + 4 * (aWidth - aRegion.x - aRegion.width)); + else + memset(aTarget + y * aStride + 4 * (aRegion.x + aRegion.width), + 0, + 4 * (aWidth - aRegion.x - aRegion.width)); +} + +NS_IMETHODIMP +nsSVGFEGaussianBlurElement::Filter(nsSVGFilterInstance *instance) +{ + nsRect rect; + nsIDOMSVGFilterPrimitiveStandardAttributes *attrib = + (nsIDOMSVGFilterPrimitiveStandardAttributes *)this; + + nsRect defaultRect; + nsAutoString input, result; + mIn1->GetAnimVal(input); + mResult->GetAnimVal(result); + instance->LookupRegion(input, &defaultRect); + + instance->GetFilterSubregion(attrib, defaultRect, &rect); + +#ifdef DEBUG_tor + fprintf(stderr, "FILTER GAUSS rect: %d,%d %dx%d\n", + rect.x, rect.y, rect.width, rect.height); +#endif + + nsCOMPtr sourceImage, targetImage; + instance->LookupImage(input, getter_AddRefs(sourceImage)); + if (!sourceImage) + return NS_ERROR_FAILURE; + + instance->GetImage(getter_AddRefs(targetImage)); + if (!targetImage) + return NS_ERROR_FAILURE; + + PRUint8 *sourceData, *targetData; + PRInt32 stride; + PRUint32 width, height, length; + sourceImage->Lock(); + targetImage->Lock(); + sourceImage->GetData(&sourceData, &length, &stride); + targetImage->GetData(&targetData, &length, &stride); + + sourceImage->GetWidth(&width); + sourceImage->GetHeight(&height); + + float stdX, stdY; + nsCOMPtr val; + mStdDeviationX->GetAnimVal(&stdX); + NS_NewSVGLength(getter_AddRefs(val), stdX); + stdX = instance->GetPrimitiveX(val); + mStdDeviationY->GetAnimVal(&stdY); + NS_NewSVGLength(getter_AddRefs(val), stdY); + stdY = instance->GetPrimitiveY(val); + + gaussianBlur(sourceData, targetData, length, stride, rect, stdX, stdY); + fixupTarget(sourceData, targetData, width, height, stride, rect); + + sourceImage->Unlock(); + targetImage->Unlock(); + + instance->DefineImage(result, targetImage); + instance->DefineRegion(result, rect); + + return NS_OK; +} + +static PRUint32 +CheckStandardNames(nsIDOMSVGAnimatedString *aStr) +{ + nsAutoString str; + aStr->GetAnimVal(str); + + if (str.Equals(NS_LITERAL_STRING("SourceGraphic"))) + return NS_FE_SOURCEGRAPHIC; + if (str.Equals(NS_LITERAL_STRING("SourceAlpha"))) + return NS_FE_SOURCEALPHA; + if (str.Equals(NS_LITERAL_STRING("BackgroundImage"))) + return NS_FE_BACKGROUNDIMAGE; + if (str.Equals(NS_LITERAL_STRING("BackgroundAlpha"))) + return NS_FE_BACKGROUNDALPHA; + if (str.Equals(NS_LITERAL_STRING("FillPaint"))) + return NS_FE_FILLPAINT; + if (str.Equals(NS_LITERAL_STRING("StrokePaint"))) + return NS_FE_STROKEPAINT; + return 0; +} + +NS_IMETHODIMP +nsSVGFEGaussianBlurElement::GetRequirements(PRUint32 *aRequirements) +{ + *aRequirements = CheckStandardNames(mIn1); + return NS_OK; +} + +//---------------------Component Transfer------------------------ + +typedef nsSVGFE nsSVGFEComponentTransferElementBase; + +class nsSVGFEComponentTransferElement : public nsSVGFEComponentTransferElementBase, + public nsIDOMSVGFEComponentTransferElement, + public nsISVGFilter +{ +protected: + friend nsresult NS_NewSVGFEComponentTransferElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEComponentTransferElement(nsINodeInfo* aNodeInfo); + nsresult Init(); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + // FE Base + NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEComponentTransferElementBase::) + + // nsISVGFilter + NS_IMETHOD Filter(nsSVGFilterInstance *instance); + NS_IMETHOD GetRequirements(PRUint32 *aRequirements); + + // Component Transfer + NS_DECL_NSIDOMSVGFECOMPONENTTRANSFERELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEComponentTransferElementBase::) + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFEComponentTransferElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFEComponentTransferElementBase::) + + // nsIContent + virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, + PRBool aNotify); + virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + +protected: + + nsCOMPtr mIn1; +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEComponentTransfer) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFEComponentTransferElement,nsSVGFEComponentTransferElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFEComponentTransferElement,nsSVGFEComponentTransferElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEComponentTransferElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEComponentTransferElement) + NS_INTERFACE_MAP_ENTRY(nsISVGFilter) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEComponentTransferElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEComponentTransferElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFEComponentTransferElement::nsSVGFEComponentTransferElement(nsINodeInfo *aNodeInfo) + : nsSVGFEComponentTransferElementBase(aNodeInfo) +{ +} + +nsresult +nsSVGFEComponentTransferElement::Init() +{ + nsresult rv = nsSVGFEComponentTransferElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // DOM property: in1 , #IMPLIED attrib: in + { + rv = NS_NewSVGAnimatedString(getter_AddRefs(mIn1)); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::in, mIn1); + NS_ENSURE_SUCCESS(rv,rv); + } + + return rv; +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEComponentTransferElement) + +//---------------------------------------------------------------------- +// nsIDOMSVGFEComponentTransferElement methods + +/* readonly attribute nsIDOMSVGAnimatedString in1; */ +NS_IMETHODIMP +nsSVGFEComponentTransferElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) +{ + *aIn = mIn1; + NS_IF_ADDREF(*aIn); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFEComponentTransferElement::Filter(nsSVGFilterInstance *instance) +{ + nsRect rect; + nsIDOMSVGFilterPrimitiveStandardAttributes *attrib = + (nsIDOMSVGFilterPrimitiveStandardAttributes *)this; + + nsRect defaultRect; + nsAutoString input, result; + mIn1->GetAnimVal(input); + mResult->GetAnimVal(result); + instance->LookupRegion(input, &defaultRect); + + instance->GetFilterSubregion(attrib, defaultRect, &rect); + +#ifdef DEBUG_tor + fprintf(stderr, "FILTER COMPONENT rect: %d,%d %dx%d\n", + rect.x, rect.y, rect.width, rect.height); +#endif + + nsCOMPtr sourceImage, targetImage; + instance->LookupImage(input, getter_AddRefs(sourceImage)); + if (!sourceImage) + return NS_ERROR_FAILURE; + + instance->GetImage(getter_AddRefs(targetImage)); + if (!targetImage) + return NS_ERROR_FAILURE; + + PRUint8 *sourceData, *targetData; + PRInt32 stride; + PRUint32 width, height, length; + sourceImage->Lock(); + targetImage->Lock(); + sourceImage->GetData(&sourceData, &length, &stride); + targetImage->GetData(&targetData, &length, &stride); + + sourceImage->GetWidth(&width); + sourceImage->GetHeight(&height); + + PRUint8 tableR[256], tableG[256], tableB[256], tableA[256]; + for (int i=0; i<256; i++) + tableR[i] = tableG[i] = tableB[i] = tableA[i] = i; + PRUint32 count = GetChildCount(); + for (PRUint32 k = 0; k < count; k++) { + nsCOMPtr child = GetChildAt(k); + nsCOMPtr elementR = do_QueryInterface(child); + nsCOMPtr elementG = do_QueryInterface(child); + nsCOMPtr elementB = do_QueryInterface(child); + nsCOMPtr elementA = do_QueryInterface(child); + if (elementR) + elementR->GenerateLookupTable(tableR); + if (elementG) + elementG->GenerateLookupTable(tableG); + if (elementB) + elementB->GenerateLookupTable(tableB); + if (elementA) + elementA->GenerateLookupTable(tableA); + } + + for (PRInt32 y = rect.y; y < rect.y + rect.height; y++) + for (PRInt32 x = rect.x; x < rect.x + rect.width; x++) { + PRUint32 r, g, b, a; + a = sourceData[y * stride + 4 * x + 3]; + if (a) { + b = tableB[(255 * (PRUint32)sourceData[y * stride + 4 * x]) / a]; + g = tableG[(255 * (PRUint32)sourceData[y * stride + 4 * x + 1]) / a]; + r = tableR[(255 * (PRUint32)sourceData[y * stride + 4 * x + 2]) / a]; + } else + b = g = r = 0; + a = tableA[a]; + targetData[y * stride + 4 * x] = (b * a) / 255; + targetData[y * stride + 4 * x + 1] = (g * a) / 255; + targetData[y * stride + 4 * x + 2] = (r * a) / 255; + targetData[y * stride + 4 * x + 3] = a; + } + + fixupTarget(sourceData, targetData, width, height, stride, rect); + + sourceImage->Unlock(); + targetImage->Unlock(); + + instance->DefineImage(result, targetImage); + instance->DefineRegion(result, rect); + + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFEComponentTransferElement::GetRequirements(PRUint32 *aRequirements) +{ + *aRequirements = CheckStandardNames(mIn1); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIContent methods + +nsresult +nsSVGFEComponentTransferElement::InsertChildAt(nsIContent* aKid, + PRUint32 aIndex, + PRBool aNotify) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + nsresult rv = nsSVGFEComponentTransferElementBase::InsertChildAt(aKid, + aIndex, + aNotify); + if (filter && value) + value->EndBatchUpdate(); + + return rv; +} + +nsresult +nsSVGFEComponentTransferElement::AppendChildTo(nsIContent* aKid, + PRBool aNotify) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + nsresult rv = nsSVGFEComponentTransferElementBase::AppendChildTo(aKid, + aNotify); + if (filter && value) + value->EndBatchUpdate(); + + return rv; +} + +nsresult +nsSVGFEComponentTransferElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + nsresult rv = nsSVGFEComponentTransferElementBase::RemoveChildAt(aIndex, + aNotify); + if (filter && value) + value->EndBatchUpdate(); + + return rv; +} + +//-------------------------------------------- + +typedef nsSVGElement nsSVGComponentTransferFunctionElementBase; + +class nsSVGComponentTransferFunctionElement : public nsSVGComponentTransferFunctionElementBase +{ +protected: + friend nsresult NS_NewSVGComponentTransferFunctionElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGComponentTransferFunctionElement(nsINodeInfo* aNodeInfo); + nsresult Init(); + + // nsISVGValueObserver interface: + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType); + +public: + // interfaces: + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT + +protected: + + // nsIDOMSVGComponentTransferFunctionElement properties: + nsCOMPtr mType; + nsCOMPtr mTableValues; + nsCOMPtr mSlope; + nsCOMPtr mIntercept; + nsCOMPtr mAmplitude; + nsCOMPtr mExponent; + nsCOMPtr mOffset; +}; + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGComponentTransferFunctionElement,nsSVGComponentTransferFunctionElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGComponentTransferFunctionElement,nsSVGComponentTransferFunctionElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGComponentTransferFunctionElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGComponentTransferFunctionElement::nsSVGComponentTransferFunctionElement(nsINodeInfo* aNodeInfo) + : nsSVGComponentTransferFunctionElementBase(aNodeInfo) +{ +} + +nsresult +nsSVGComponentTransferFunctionElement::Init() +{ + nsresult rv; + + // enumeration mappings + static struct nsSVGEnumMapping gComponentTransferTypes[] = { + {&nsSVGAtoms::identity, + nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, + {&nsSVGAtoms::table, + nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, + {&nsSVGAtoms::discrete, + nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, + {&nsSVGAtoms::linear, + nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, + {&nsSVGAtoms::gamma, + nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, + {nsnull, 0} + }; + + // Create mapped properties: + + // DOM property: type, #IMPLIED attrib: type + { + nsCOMPtr types; + rv = NS_NewSVGEnum(getter_AddRefs(types), + nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY, + gComponentTransferTypes); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mType), types); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::type, mType); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: tableValues, #IMPLIED attrib: tableValues + { + nsCOMPtr values; + rv = NS_NewSVGNumberList(getter_AddRefs(values)); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mTableValues), values); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::tableValues, mTableValues); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: slope , #IMPLIED attrib: slope + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mSlope), 1.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::slope, mSlope); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: intercept , #IMPLIED attrib: intercept + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mIntercept), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::intercept, mIntercept); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: amplitude , #IMPLIED attrib: amplitude + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mAmplitude), 1.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::amplitude, mAmplitude); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: exponent , #IMPLIED attrib: exponent + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mExponent), 1.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::exponent, mExponent); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: offset , #IMPLIED attrib: offset + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mOffset), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::offset, mOffset); + NS_ENSURE_SUCCESS(rv,rv); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsSVGComponentTransferFunctionElement::WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + nsCOMPtr element; + nsCOMPtr filter; + element = do_QueryInterface(GetParent()); + if (GetParent()) + filter = do_QueryInterface(GetParent()->GetParent()); + nsCOMPtr value = do_QueryInterface(filter); + + if (element && filter && value) + value->BeginBatchUpdate(); + return nsSVGComponentTransferFunctionElementBase::WillModifySVGObservable(observable, aModType); +} + +NS_IMETHODIMP +nsSVGComponentTransferFunctionElement::DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + nsCOMPtr element; + nsCOMPtr filter; + element = do_QueryInterface(GetParent()); + if (GetParent()) + filter = do_QueryInterface(GetParent()->GetParent()); + nsCOMPtr value = do_QueryInterface(filter); + + if (element && filter && value) + value->EndBatchUpdate(); + return nsSVGComponentTransferFunctionElementBase::DidModifySVGObservable(observable, aModType); +} + +//---------------------------------------------------------------------- +// nsIDOMSVGComponentTransferFunctionElement methods + +/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) +{ + *aType = mType; + NS_IF_ADDREF(*aType); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumberList tableValues; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetTableValues(nsIDOMSVGAnimatedNumberList * *aTableValues) +{ + *aTableValues = mTableValues; + NS_IF_ADDREF(*aTableValues); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber slope; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetSlope(nsIDOMSVGAnimatedNumber * *aSlope) +{ + *aSlope = mSlope; + NS_IF_ADDREF(*aSlope); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber intercept; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetIntercept(nsIDOMSVGAnimatedNumber * *aIntercept) +{ + *aIntercept = mIntercept; + NS_IF_ADDREF(*aIntercept); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber amplitude; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetAmplitude(nsIDOMSVGAnimatedNumber * *aAmplitude) +{ + *aAmplitude = mAmplitude; + NS_IF_ADDREF(*aAmplitude); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber exponent; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetExponent(nsIDOMSVGAnimatedNumber * *aExponent) +{ + *aExponent = mExponent; + NS_IF_ADDREF(*aExponent); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber offset; */ +NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetOffset(nsIDOMSVGAnimatedNumber * *aOffset) +{ + *aOffset = mOffset; + NS_IF_ADDREF(*aOffset); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGComponentTransferFunctionElement::GenerateLookupTable(PRUint8 *aTable) +{ + PRUint16 type; + mType->GetAnimVal(&type); + + PRUint32 i; + + switch (type) { + case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_TABLE: + { + nsCOMPtr list; + nsCOMPtr number; + mTableValues->GetAnimVal(getter_AddRefs(list)); + PRUint32 num = 0; + if (list) + list->GetNumberOfItems(&num); + if (num <= 1) + break; + + for (i = 0; i < 256; i++) { + PRInt32 k = (i * (num - 1)) / 255; + float v1, v2; + list->GetItem(k, getter_AddRefs(number)); + number->GetValue(&v1); + list->GetItem(PR_MIN(k + 1, num - 1), getter_AddRefs(number)); + number->GetValue(&v2); + PRInt32 val = + PRInt32(255 * (v1 + (i/255.0f - k/float(num-1))*(num - 1)*(v2 - v1))); + val = PR_MIN(255, val); + val = PR_MAX(0, val); + aTable[i] = val; + } + break; + } + + case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: + { + nsCOMPtr list; + nsCOMPtr number; + mTableValues->GetAnimVal(getter_AddRefs(list)); + PRUint32 num = 0; + if (list) + list->GetNumberOfItems(&num); + if (num <= 1) + break; + + for (i = 0; i < 256; i++) { + PRInt32 k = (i * (num - 1)) / 255; + float v; + list->GetItem(k, getter_AddRefs(number)); + number->GetValue(&v); + PRInt32 val = PRInt32(255 * v); + val = PR_MIN(255, val); + val = PR_MAX(0, val); + aTable[i] = val; + } + break; + } + + case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: + { + float slope, intercept; + mSlope->GetAnimVal(&slope); + mIntercept->GetAnimVal(&intercept); + for (i = 0; i < 256; i++) { + PRInt32 val = PRInt32(slope * i + 255 * intercept); + val = PR_MIN(255, val); + val = PR_MAX(0, val); + aTable[i] = val; + } + break; + } + + case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: + { + float amplitude, exponent, offset; + mAmplitude->GetAnimVal(&litude); + mExponent->GetAnimVal(&exponent); + mOffset->GetAnimVal(&offset); + for (i = 0; i < 256; i++) { + PRInt32 val = PRInt32(255 * (amplitude * pow(i / 255.0f, exponent) + offset)); + val = PR_MIN(255, val); + val = PR_MAX(0, val); + aTable[i] = val; + } + break; + } + + case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: + default: + break; + } + + return NS_OK; +} + +class nsSVGFEFuncRElement : public nsSVGComponentTransferFunctionElement, + public nsIDOMSVGFEFuncRElement +{ +protected: + friend nsresult NS_NewSVGFEFuncRElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEFuncRElement(nsINodeInfo* aNodeInfo) + : nsSVGComponentTransferFunctionElement(aNodeInfo) {} + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::) + + NS_DECL_NSIDOMSVGFEFUNCRELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::) + +protected: +}; + +NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncRElement,nsSVGComponentTransferFunctionElement) +NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncRElement,nsSVGComponentTransferFunctionElement) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEFuncRElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGComponentTransferFunctionElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEFuncRElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEFuncRElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement) + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncR) +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEFuncRElement) + + +class nsSVGFEFuncGElement : public nsSVGComponentTransferFunctionElement, + public nsIDOMSVGFEFuncGElement +{ +protected: + friend nsresult NS_NewSVGFEFuncGElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEFuncGElement(nsINodeInfo* aNodeInfo) + : nsSVGComponentTransferFunctionElement(aNodeInfo) {} + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::) + + NS_DECL_NSIDOMSVGFEFUNCGELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::) + +protected: +}; + +NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncGElement,nsSVGComponentTransferFunctionElement) +NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncGElement,nsSVGComponentTransferFunctionElement) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEFuncGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGComponentTransferFunctionElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEFuncGElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEFuncGElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement) + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncG) +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEFuncGElement) + + +class nsSVGFEFuncBElement : public nsSVGComponentTransferFunctionElement, + public nsIDOMSVGFEFuncBElement +{ +protected: + friend nsresult NS_NewSVGFEFuncBElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEFuncBElement(nsINodeInfo* aNodeInfo) + : nsSVGComponentTransferFunctionElement(aNodeInfo) {} + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::) + + NS_DECL_NSIDOMSVGFEFUNCBELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::) + +protected: +}; + +NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncBElement,nsSVGComponentTransferFunctionElement) +NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncBElement,nsSVGComponentTransferFunctionElement) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEFuncBElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGComponentTransferFunctionElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEFuncBElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEFuncBElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement) + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncB) +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEFuncBElement) + + +class nsSVGFEFuncAElement : public nsSVGComponentTransferFunctionElement, + public nsIDOMSVGFEFuncAElement +{ +protected: + friend nsresult NS_NewSVGFEFuncAElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEFuncAElement(nsINodeInfo* aNodeInfo) + : nsSVGComponentTransferFunctionElement(aNodeInfo) {} + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::) + + NS_DECL_NSIDOMSVGFEFUNCAELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGComponentTransferFunctionElement::) + NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::) + +protected: +}; + +NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncAElement,nsSVGComponentTransferFunctionElement) +NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncAElement,nsSVGComponentTransferFunctionElement) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEFuncAElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGComponentTransferFunctionElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEFuncAElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEFuncAElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement) + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncA) +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEFuncAElement) + +//---------------------Merge------------------------ + +typedef nsSVGFE nsSVGFEMergeElementBase; + +class nsSVGFEMergeElement : public nsSVGFEMergeElementBase, + public nsIDOMSVGFEMergeElement, + public nsISVGFilter +{ +protected: + friend nsresult NS_NewSVGFEMergeElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEMergeElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGFEMergeElement(); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + // FE Base + NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMergeElementBase::) + + // nsISVGFilter + NS_IMETHOD Filter(nsSVGFilterInstance *instance); + NS_IMETHOD GetRequirements(PRUint32 *aRequirements); + + // Gaussian + NS_DECL_NSIDOMSVGFEMERGEELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeElementBase::) + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFEMergeElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFEMergeElementBase::) + + // nsIContent + virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, + PRBool aNotify); + virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + +protected: + +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEMerge) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFEMergeElement,nsSVGFEMergeElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFEMergeElement,nsSVGFEMergeElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEMergeElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEMergeElement) + NS_INTERFACE_MAP_ENTRY(nsISVGFilter) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEMergeElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFEMergeElement::nsSVGFEMergeElement(nsINodeInfo *aNodeInfo) + : nsSVGFEMergeElementBase(aNodeInfo) +{ +} + +nsSVGFEMergeElement::~nsSVGFEMergeElement() +{ +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEMergeElement) + +NS_IMETHODIMP +nsSVGFEMergeElement::Filter(nsSVGFilterInstance *instance) +{ + nsRect rect; + nsIDOMSVGFilterPrimitiveStandardAttributes *attrib = + (nsIDOMSVGFilterPrimitiveStandardAttributes *)this; + + nsCOMPtr sourceImage, targetImage; + instance->GetImage(getter_AddRefs(targetImage)); + if (!targetImage) + return NS_ERROR_FAILURE; + + PRUint8 *sourceData, *targetData; + PRInt32 stride; + PRUint32 width, height, length; + targetImage->Lock(); + targetImage->GetData(&targetData, &length, &stride); + + PRUint32 count = GetChildCount(); + for (PRUint32 i = 0; i < count; i++) { + nsCOMPtr child = GetChildAt(i); + nsCOMPtr node = do_QueryInterface(child); + if (!node) + continue; + nsCOMPtr str; + node->GetIn1(getter_AddRefs(str)); + + nsRect defaultRect; + nsAutoString input; + str->GetAnimVal(input); + instance->LookupRegion(input, &defaultRect); + + instance->GetFilterSubregion(attrib, defaultRect, &rect); + +#ifdef DEBUG_tor + fprintf(stderr, "FILTER MERGE rect: %d,%d %dx%d\n", + rect.x, rect.y, rect.width, rect.height); +#endif + + instance->LookupImage(input, getter_AddRefs(sourceImage)); + if (!sourceImage) { + targetImage->Unlock(); + return NS_ERROR_FAILURE; + } + + sourceImage->Lock(); + sourceImage->GetData(&sourceData, &length, &stride); + + sourceImage->GetWidth(&width); + sourceImage->GetHeight(&height); + +#define BLEND(target, source, alpha) \ + target = PR_MIN(255, (target * (255 - alpha))/255 + source) + + for (PRInt32 y = rect.y; y < rect.y + rect.height; y++) + for (PRInt32 x = rect.x; x < rect.x + rect.width; x++) { + PRUint32 a = sourceData[y * stride + 4 * x + 3]; + BLEND(targetData[y * stride + 4 * x ], + sourceData[y * stride + 4 * x ], a); + BLEND(targetData[y * stride + 4 * x + 1], + sourceData[y * stride + 4 * x + 1], a); + BLEND(targetData[y * stride + 4 * x + 2], + sourceData[y * stride + 4 * x + 2], a); + BLEND(targetData[y * stride + 4 * x + 3], + sourceData[y * stride + 4 * x + 3], a); + } +#undef BLEND + + sourceImage->Unlock(); + } + + fixupTarget(nsnull, targetData, width, height, stride, rect); + + targetImage->Unlock(); + + nsAutoString result; + mResult->GetAnimVal(result); + instance->DefineImage(result, targetImage); + instance->DefineRegion(result, rect); + + return NS_OK; +} + + +NS_IMETHODIMP +nsSVGFEMergeElement::GetRequirements(PRUint32 *aRequirements) +{ + *aRequirements = 0; + + PRUint32 count = GetChildCount(); + for (PRUint32 i = 0; i < count; i++) { + nsCOMPtr child = GetChildAt(i); + nsCOMPtr node = do_QueryInterface(child); + if (node) { + nsCOMPtr str; + node->GetIn1(getter_AddRefs(str)); + *aRequirements |= CheckStandardNames(str); + } + } + + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIContent methods + +nsresult +nsSVGFEMergeElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, + PRBool aNotify) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + nsresult rv = nsSVGFEMergeElementBase::InsertChildAt(aKid, aIndex, aNotify); + if (filter && value) + value->EndBatchUpdate(); + + return rv; +} + +nsresult +nsSVGFEMergeElement::AppendChildTo(nsIContent* aKid, PRBool aNotify) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + nsresult rv = nsSVGFEMergeElementBase::AppendChildTo(aKid, aNotify); + if (filter && value) + value->EndBatchUpdate(); + + return rv; +} + +nsresult +nsSVGFEMergeElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +{ + nsCOMPtr filter = do_QueryInterface(GetParent()); + nsCOMPtr value = do_QueryInterface(GetParent()); + if (filter && value) + value->BeginBatchUpdate(); + nsresult rv = nsSVGFEMergeElementBase::RemoveChildAt(aIndex, aNotify); + if (filter && value) + value->EndBatchUpdate(); + + return rv; +} + +//---------------------Merge Node------------------------ + +typedef nsSVGStylableElement nsSVGFEMergeNodeElementBase; + +class nsSVGFEMergeNodeElement : public nsSVGFEMergeNodeElementBase, + public nsIDOMSVGFEMergeNodeElement +{ +protected: + friend nsresult NS_NewSVGFEMergeNodeElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEMergeNodeElement(nsINodeInfo* aNodeInfo); + nsresult Init(); + + // nsISVGValueObserver interface: + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_NSIDOMSVGFEMERGENODEELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeNodeElementBase::) + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFEMergeNodeElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFEMergeNodeElementBase::) + +protected: + nsCOMPtr mIn1; +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEMergeNode) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFEMergeNodeElement,nsSVGFEMergeNodeElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFEMergeNodeElement,nsSVGFEMergeNodeElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEMergeNodeElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEMergeNodeElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEMergeNodeElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeNodeElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFEMergeNodeElement::nsSVGFEMergeNodeElement(nsINodeInfo *aNodeInfo) + : nsSVGFEMergeNodeElementBase(aNodeInfo) +{ +} + +nsresult +nsSVGFEMergeNodeElement::Init() +{ + nsresult rv = nsSVGFEMergeNodeElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // DOM property: in1 , #IMPLIED attrib: in + { + rv = NS_NewSVGAnimatedString(getter_AddRefs(mIn1)); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::in, mIn1); + NS_ENSURE_SUCCESS(rv,rv); + } + + return rv; +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEMergeNodeElement) + +NS_IMETHODIMP +nsSVGFEMergeNodeElement::WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + nsCOMPtr element; + nsCOMPtr filter; + element = do_QueryInterface(GetParent()); + if (GetParent()) + filter = do_QueryInterface(GetParent()->GetParent()); + nsCOMPtr value = do_QueryInterface(filter); + + if (element && filter && value) + value->BeginBatchUpdate(); + return nsSVGFEMergeNodeElementBase::WillModifySVGObservable(observable, aModType); +} + +NS_IMETHODIMP +nsSVGFEMergeNodeElement::DidModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + nsCOMPtr element; + nsCOMPtr filter; + element = do_QueryInterface(GetParent()); + if (GetParent()) + filter = do_QueryInterface(GetParent()->GetParent()); + nsCOMPtr value = do_QueryInterface(filter); + + if (element && filter && value) + value->EndBatchUpdate(); + return nsSVGFEMergeNodeElementBase::DidModifySVGObservable(observable, aModType); +} + +//---------------------------------------------------------------------- +// nsIDOMSVGFEMergeNodeElement methods + +/* readonly attribute nsIDOMSVGAnimatedString in1; */ +NS_IMETHODIMP nsSVGFEMergeNodeElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) +{ + *aIn = mIn1; + NS_IF_ADDREF(*aIn); + return NS_OK; +} + + +//---------------------Offset------------------------ + +typedef nsSVGFE nsSVGFEOffsetElementBase; + +class nsSVGFEOffsetElement : public nsSVGFEOffsetElementBase, + public nsIDOMSVGFEOffsetElement, + public nsISVGFilter +{ +protected: + friend nsresult NS_NewSVGFEOffsetElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEOffsetElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGFEOffsetElement(); + nsresult Init(); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + // FE Base + NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEOffsetElementBase::) + + // nsISVGFilter + NS_IMETHOD Filter(nsSVGFilterInstance *instance); + NS_IMETHOD GetRequirements(PRUint32 *aRequirements); + + // Offset + NS_DECL_NSIDOMSVGFEOFFSETELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEOffsetElementBase::) + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFEOffsetElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFEOffsetElementBase::) + +protected: + + nsCOMPtr mDx; + nsCOMPtr mDy; + nsCOMPtr mIn1; +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEOffset) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFEOffsetElement,nsSVGFEOffsetElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFEOffsetElement,nsSVGFEOffsetElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEOffsetElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEOffsetElement) + NS_INTERFACE_MAP_ENTRY(nsISVGFilter) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEOffsetElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEOffsetElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFEOffsetElement::nsSVGFEOffsetElement(nsINodeInfo *aNodeInfo) + : nsSVGFEOffsetElementBase(aNodeInfo) +{ +} + +nsSVGFEOffsetElement::~nsSVGFEOffsetElement() +{ +} + +nsresult +nsSVGFEOffsetElement::Init() +{ + nsresult rv = nsSVGFEOffsetElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // DOM property: in1 , #IMPLIED attrib: in + { + rv = NS_NewSVGAnimatedString(getter_AddRefs(mIn1)); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::in, mIn1); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: dx , #IMPLIED attrib: dx + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mDx), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::dx, mDx); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: dy , #IMPLIED attrib: dy + { + rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mDy), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::dy, mDy); + NS_ENSURE_SUCCESS(rv,rv); + } + + return rv; +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEOffsetElement) + + +//---------------------------------------------------------------------- +// nsIDOMSVGFEOffsetElement methods + +/* readonly attribute nsIDOMSVGAnimatedString in1; */ +NS_IMETHODIMP nsSVGFEOffsetElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) +{ + *aIn = mIn1; + NS_IF_ADDREF(*aIn); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber dx; */ +NS_IMETHODIMP nsSVGFEOffsetElement::GetDx(nsIDOMSVGAnimatedNumber * *aDx) +{ + *aDx = mDx; + NS_IF_ADDREF(*aDx); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumber dy; */ +NS_IMETHODIMP nsSVGFEOffsetElement::GetDy(nsIDOMSVGAnimatedNumber * *aDy) +{ + *aDy = mDy; + NS_IF_ADDREF(*aDy); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFEOffsetElement::Filter(nsSVGFilterInstance *instance) +{ + nsRect rect; + nsIDOMSVGFilterPrimitiveStandardAttributes *attrib = + (nsIDOMSVGFilterPrimitiveStandardAttributes *)this; + + nsRect defaultRect; + nsAutoString input, result; + mIn1->GetAnimVal(input); + mResult->GetAnimVal(result); + instance->LookupRegion(input, &defaultRect); + + instance->GetFilterSubregion(attrib, defaultRect, &rect); + +#ifdef DEBUG_tor + fprintf(stderr, "FILTER OFFSET rect: %d,%d %dx%d\n", + rect.x, rect.y, rect.width, rect.height); +#endif + + nsCOMPtr sourceImage, targetImage; + instance->LookupImage(input, getter_AddRefs(sourceImage)); + if (!sourceImage) + return NS_ERROR_FAILURE; + + instance->GetImage(getter_AddRefs(targetImage)); + if (!targetImage) + return NS_ERROR_FAILURE; + + PRUint8 *sourceData, *targetData; + PRInt32 stride; + PRUint32 width, height, length; + sourceImage->Lock(); + targetImage->Lock(); + sourceImage->GetData(&sourceData, &length, &stride); + targetImage->GetData(&targetData, &length, &stride); + + sourceImage->GetWidth(&width); + sourceImage->GetHeight(&height); + + PRInt32 offsetX, offsetY; + float flt; + nsCOMPtr val; + mDx->GetAnimVal(&flt); + NS_NewSVGLength(getter_AddRefs(val), flt); + offsetX = instance->GetPrimitiveX(val); + mDy->GetAnimVal(&flt); + NS_NewSVGLength(getter_AddRefs(val), flt); + offsetY = instance->GetPrimitiveY(val); + + + for (PRInt32 y = rect.y; y < rect.y + rect.height; y++) { + PRInt32 targetRow = y + offsetY; + if (targetRow < rect.y || targetRow >= rect.y + rect.height) + continue; + + PRInt32 targetColumn = rect.x + offsetX; + if (targetColumn < rect.x) + memcpy(targetData + stride * targetRow + 4 * rect.x, + sourceData + stride * y - 4 * offsetX, + 4 * (rect.width + offsetX)); + else + memcpy(targetData + stride * targetRow + 4 * targetColumn, + sourceData + stride * y + 4 * rect.x, + 4 * (rect.width - offsetX)); + } + + fixupTarget(sourceData, targetData, width, height, stride, rect); + + sourceImage->Unlock(); + targetImage->Unlock(); + + instance->DefineImage(result, targetImage); + instance->DefineRegion(result, rect); + + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFEOffsetElement::GetRequirements(PRUint32 *aRequirements) +{ + *aRequirements = CheckStandardNames(mIn1); + return NS_OK; +} + + +//---------------------UnimplementedMOZ------------------------ + +typedef nsSVGFE nsSVGFEUnimplementedMOZElementBase; + +class nsSVGFEUnimplementedMOZElement : public nsSVGFEUnimplementedMOZElementBase, + public nsIDOMSVGFEUnimplementedMOZElement, + public nsISVGFilter +{ +protected: + friend nsresult NS_NewSVGFEUnimplementedMOZElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGFEUnimplementedMOZElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGFEUnimplementedMOZElement(); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + // FE Base + NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEUnimplementedMOZElementBase::) + + // nsISVGFilter + NS_IMETHOD Filter(nsSVGFilterInstance *instance); + NS_IMETHOD GetRequirements(PRUint32 *aRequirements); + + // Gaussian + NS_DECL_NSIDOMSVGFEMERGEELEMENT + + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEUnimplementedMOZElementBase::) + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGFEUnimplementedMOZElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGFEUnimplementedMOZElementBase::) + +protected: + +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(FEUnimplementedMOZ) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFEUnimplementedMOZElement,nsSVGFEUnimplementedMOZElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFEUnimplementedMOZElement,nsSVGFEUnimplementedMOZElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFEUnimplementedMOZElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEUnimplementedMOZElement) + NS_INTERFACE_MAP_ENTRY(nsISVGFilter) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEUnimplementedMOZElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEUnimplementedMOZElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGFEUnimplementedMOZElement::nsSVGFEUnimplementedMOZElement(nsINodeInfo *aNodeInfo) + : nsSVGFEUnimplementedMOZElementBase(aNodeInfo) +{ +} + +nsSVGFEUnimplementedMOZElement::~nsSVGFEUnimplementedMOZElement() +{ +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGFEUnimplementedMOZElement) + +NS_IMETHODIMP +nsSVGFEUnimplementedMOZElement::Filter(nsSVGFilterInstance *instance) +{ + /* should never be called */ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsSVGFEUnimplementedMOZElement::GetRequirements(PRUint32 *aRequirements) +{ + /* should never be called */ + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/mozilla/content/svg/content/src/nsSVGGraphicElement.cpp b/mozilla/content/svg/content/src/nsSVGGraphicElement.cpp index 88edddeed76..cf8f909e8e5 100644 --- a/mozilla/content/svg/content/src/nsSVGGraphicElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGGraphicElement.cpp @@ -132,10 +132,10 @@ NS_IMETHODIMP nsSVGGraphicElement::GetBBox(nsIDOMSVGRect **_retval) NS_ASSERTION(svgframe, "wrong frame type"); if (svgframe) { svgframe->SetMatrixPropagation(PR_FALSE); - svgframe->NotifyCanvasTMChanged(); + svgframe->NotifyCanvasTMChanged(PR_TRUE); nsresult rv = svgframe->GetBBox(_retval); svgframe->SetMatrixPropagation(PR_TRUE); - svgframe->NotifyCanvasTMChanged(); + svgframe->NotifyCanvasTMChanged(PR_TRUE); return rv; } } diff --git a/mozilla/content/svg/content/src/nsSVGSVGElement.cpp b/mozilla/content/svg/content/src/nsSVGSVGElement.cpp index 4f72f6603f8..fd2ee3cee2b 100644 --- a/mozilla/content/svg/content/src/nsSVGSVGElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGSVGElement.cpp @@ -981,10 +981,10 @@ nsSVGSVGElement::GetBBox(nsIDOMSVGRect **_retval) frame->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&svgframe); if (svgframe) { svgframe->SetMatrixPropagation(PR_FALSE); - svgframe->NotifyCanvasTMChanged(); + svgframe->NotifyCanvasTMChanged(PR_TRUE); nsresult rv = svgframe->GetBBox(_retval); svgframe->SetMatrixPropagation(PR_TRUE); - svgframe->NotifyCanvasTMChanged(); + svgframe->NotifyCanvasTMChanged(PR_TRUE); return rv; } else { // XXX: outer svg diff --git a/mozilla/dom/public/idl/svg/Makefile.in b/mozilla/dom/public/idl/svg/Makefile.in index 1a6c566ff1f..db06ff97150 100644 --- a/mozilla/dom/public/idl/svg/Makefile.in +++ b/mozilla/dom/public/idl/svg/Makefile.in @@ -53,6 +53,7 @@ XPIDLSRCS = \ nsIDOMSVGAngle.idl \ nsIDOMSVGAnimatedAngle.idl \ nsIDOMSVGAnimatedEnum.idl \ + nsIDOMSVGAnimatedInteger.idl \ nsIDOMSVGAnimatedLength.idl \ nsIDOMSVGAnimatedLengthList.idl \ nsIDOMSVGAnimatedNumber.idl \ @@ -72,6 +73,8 @@ XPIDLSRCS = \ nsIDOMSVGEllipseElement.idl \ nsIDOMSVGEvent.idl \ nsIDOMSVGException.idl \ + nsIDOMSVGFilterElement.idl \ + nsIDOMSVGFilters.idl \ nsIDOMSVGFitToViewBox.idl \ nsIDOMSVGForeignObjectElem.idl \ nsIDOMSVGGElement.idl \ diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedInteger.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedInteger.idl new file mode 100644 index 00000000000..f2243a80e97 --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedInteger.idl @@ -0,0 +1,61 @@ +/* -*- Mode: IDL; 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. + * + * Parts of this file contain code derived from the following files(s) + * of the Mozilla SVG project (these parts are Copyright (C) by their + * respective copyright-holders): + * dom/public/idl/svg/nsIDOMSVGAnimatedNumber.idl + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 NPL, 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 "domstubs.idl" + +/** + * The nsIDOMSVGAnimatedNumber interface is the interface to an SVG + * Animated Integer. + * + * For more information on this interface please see + * http://www.w3.org/TR/SVG11/types.html + * + */ + +[scriptable, uuid(7b196db6-955e-4a9f-8f42-645ebc2ce938)] +interface nsIDOMSVGAnimatedInteger : nsISupports +{ + attribute long baseVal; + // raises DOMException on setting + readonly attribute long animVal; +}; + + diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGFilterElement.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGFilterElement.idl new file mode 100644 index 00000000000..63e36964c66 --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGFilterElement.idl @@ -0,0 +1,79 @@ +/* -*- Mode: IDL; 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) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 "nsIDOMSVGElement.idl" + +interface nsIDOMSVGAnimatedLength; +interface nsIDOMSVGAnimatedEnumeration; +interface nsIDOMSVGAnimatedInteger; + +[scriptable, uuid(9e81d4ae-190c-4b9d-a076-ebc52a7bf231)] +interface nsIDOMSVGFilterElement + : nsIDOMSVGElement +/* + The SVG DOM makes use of multiple interface inheritance. + Since XPCOM only supports single interface inheritance, + the best thing that we can do is to promise that whenever + an object implements _this_ interface it will also + implement the following interfaces. (We then have to QI to + hop between them.) + + nsIDOMSVGElement, + nsIDOMSVGURIReference, + nsIDOMSVGLangSpace, + nsIDOMSVGExternalResourcesRequired, + nsIDOMSVGStylable, +*/ +{ + // These constants are taken from SVGUnitTypes + const unsigned short SVG_FUNITS_UNKNOWN = 0; + const unsigned short SVG_FUNITS_OBJECTBOUNDINGBOX = 1; + const unsigned short SVG_FUNITS_USERSPACEONUSE = 2; + + readonly attribute nsIDOMSVGAnimatedEnumeration filterUnits; + readonly attribute nsIDOMSVGAnimatedEnumeration primitiveUnits; + readonly attribute nsIDOMSVGAnimatedLength x; + readonly attribute nsIDOMSVGAnimatedLength y; + readonly attribute nsIDOMSVGAnimatedLength width; + readonly attribute nsIDOMSVGAnimatedLength height; + + readonly attribute nsIDOMSVGAnimatedInteger filterResX; + readonly attribute nsIDOMSVGAnimatedInteger filterResY; + + void setFilterRes (in unsigned long filterResX, in unsigned long filterResY); +}; + + diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGFilters.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGFilters.idl new file mode 100644 index 00000000000..32b0a9ecf38 --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGFilters.idl @@ -0,0 +1,136 @@ +/* -*- Mode: IDL; 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) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 "nsIDOMSVGElement.idl" +#include "nsIDOMSVGStylable.idl" + +interface nsIDOMSVGAnimatedLength; +interface nsIDOMSVGAnimatedString; +interface nsIDOMSVGAnimatedNumber; +interface nsIDOMSVGAnimatedEnumeration; +interface nsIDOMSVGAnimatedNumberList; + +[scriptable, uuid(ab68567a-b830-4c46-9f2f-a28513a9e980)] +interface nsIDOMSVGFilterPrimitiveStandardAttributes : nsIDOMSVGElement +{ + readonly attribute nsIDOMSVGAnimatedLength x; + readonly attribute nsIDOMSVGAnimatedLength y; + readonly attribute nsIDOMSVGAnimatedLength width; + readonly attribute nsIDOMSVGAnimatedLength height; + readonly attribute nsIDOMSVGAnimatedString result; +}; + +[scriptable, uuid(43ff8d42-3380-4dbd-a916-7c2daa3ed7f4)] +interface nsIDOMSVGFEGaussianBlurElement : nsIDOMSVGFilterPrimitiveStandardAttributes +{ + readonly attribute nsIDOMSVGAnimatedString in1; + readonly attribute nsIDOMSVGAnimatedNumber stdDeviationX; + readonly attribute nsIDOMSVGAnimatedNumber stdDeviationY; + + void setStdDeviation ( in float stdDeviationX, in float stdDeviationY ); +}; + +[scriptable, uuid(4de6b44a-f909-4948-bc43-5ee2ca6de55b)] +interface nsIDOMSVGFEComponentTransferElement : nsIDOMSVGFilterPrimitiveStandardAttributes +{ + readonly attribute nsIDOMSVGAnimatedString in1; +}; + + +[scriptable, uuid(dfdb8833-0e7d-407d-acac-18e563ea94e8)] +interface nsIDOMSVGComponentTransferFunctionElement : nsIDOMSVGElement +{ + // Component Transfer Types + const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; + const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; + const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; + const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; + const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; + const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; + + readonly attribute nsIDOMSVGAnimatedEnumeration type; + readonly attribute nsIDOMSVGAnimatedNumberList tableValues; + readonly attribute nsIDOMSVGAnimatedNumber slope; + readonly attribute nsIDOMSVGAnimatedNumber intercept; + readonly attribute nsIDOMSVGAnimatedNumber amplitude; + readonly attribute nsIDOMSVGAnimatedNumber exponent; + readonly attribute nsIDOMSVGAnimatedNumber offset; + + [noscript] void GenerateLookupTable(out PRUint8 aTable); +}; + +[scriptable, uuid(85719a5d-9688-4c5f-bad5-c21847515200)] +interface nsIDOMSVGFEFuncRElement : nsIDOMSVGComponentTransferFunctionElement +{ +}; + +[scriptable, uuid(28555e78-c6c2-4a98-af53-bfc2c6944295)] +interface nsIDOMSVGFEFuncGElement : nsIDOMSVGComponentTransferFunctionElement +{ +}; + +[scriptable, uuid(8b139fe7-5d21-4af3-beda-414aa089b3fb)] +interface nsIDOMSVGFEFuncBElement : nsIDOMSVGComponentTransferFunctionElement +{ +}; + +[scriptable, uuid(fa48511c-283a-437f-9507-c309ac6f0f57)] +interface nsIDOMSVGFEFuncAElement : nsIDOMSVGComponentTransferFunctionElement +{ +}; + +[scriptable, uuid(b860512c-2547-4d1f-bb43-b57b54d39014)] +interface nsIDOMSVGFEMergeElement : nsIDOMSVGFilterPrimitiveStandardAttributes +{ +}; + +[scriptable, uuid(540c3447-4b07-4bd3-84df-30f66b68df14)] +interface nsIDOMSVGFEMergeNodeElement : nsIDOMSVGElement { + readonly attribute nsIDOMSVGAnimatedString in1; +}; + +[scriptable, uuid(c080f191-b22c-4fc0-85d5-a79dc3fa7ec8)] +interface nsIDOMSVGFEOffsetElement : nsIDOMSVGFilterPrimitiveStandardAttributes { + readonly attribute nsIDOMSVGAnimatedString in1; + readonly attribute nsIDOMSVGAnimatedNumber dx; + readonly attribute nsIDOMSVGAnimatedNumber dy; +}; + + +[scriptable, uuid(8698c635-26c7-468b-905e-494e8825d56b)] +interface nsIDOMSVGFEUnimplementedMOZElement : nsIDOMSVGFilterPrimitiveStandardAttributes +{ +}; diff --git a/mozilla/dom/public/nsIDOMClassInfo.h b/mozilla/dom/public/nsIDOMClassInfo.h index 45633ed2237..dbdc06e6b04 100644 --- a/mozilla/dom/public/nsIDOMClassInfo.h +++ b/mozilla/dom/public/nsIDOMClassInfo.h @@ -253,6 +253,17 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGDefsElement_id, eDOMClassInfo_SVGDescElement_id, eDOMClassInfo_SVGEllipseElement_id, + eDOMClassInfo_SVGFEComponentTransferElement_id, + eDOMClassInfo_SVGFEFuncAElement_id, + eDOMClassInfo_SVGFEFuncBElement_id, + eDOMClassInfo_SVGFEFuncGElement_id, + eDOMClassInfo_SVGFEFuncRElement_id, + eDOMClassInfo_SVGFEGaussianBlurElement_id, + eDOMClassInfo_SVGFEMergeElement_id, + eDOMClassInfo_SVGFEMergeNodeElement_id, + eDOMClassInfo_SVGFEOffsetElement_id, + eDOMClassInfo_SVGFEUnimplementedMOZElement_id, + eDOMClassInfo_SVGFilterElement_id, eDOMClassInfo_SVGGElement_id, eDOMClassInfo_SVGGradientElement_id, eDOMClassInfo_SVGImageElement_id, @@ -280,6 +291,7 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGAngle_id, eDOMClassInfo_SVGAnimatedAngle_id, eDOMClassInfo_SVGAnimatedEnumeration_id, + eDOMClassInfo_SVGAnimatedInteger_id, eDOMClassInfo_SVGAnimatedLength_id, eDOMClassInfo_SVGAnimatedLengthList_id, eDOMClassInfo_SVGAnimatedNumber_id, diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 1b73d650cb7..88e5183c5a8 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -319,6 +319,7 @@ #include "nsIDOMSVGAngle.h" #include "nsIDOMSVGAnimatedAngle.h" #include "nsIDOMSVGAnimatedEnum.h" +#include "nsIDOMSVGAnimatedInteger.h" #include "nsIDOMSVGAnimatedLength.h" #include "nsIDOMSVGAnimatedLengthList.h" #include "nsIDOMSVGAnimatedNumber.h" @@ -338,6 +339,8 @@ #include "nsIDOMSVGEllipseElement.h" #include "nsIDOMSVGEvent.h" #include "nsIDOMSVGException.h" +#include "nsIDOMSVGFilterElement.h" +#include "nsIDOMSVGFilters.h" #include "nsIDOMSVGFitToViewBox.h" #ifdef MOZ_SVG_FOREIGNOBJECT #include "nsIDOMSVGForeignObjectElem.h" @@ -864,6 +867,28 @@ static nsDOMClassInfoData sClassInfoData[] = { ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGEllipseElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEComponentTransferElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEFuncAElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEFuncBElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEFuncGElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEFuncRElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEGaussianBlurElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEMergeElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEMergeNodeElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEOffsetElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFEUnimplementedMOZElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGFilterElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGGElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGGradientElement, nsElementSH, @@ -916,6 +941,8 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedEnumeration, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGAnimatedInteger, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedLength, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedLengthList, nsDOMGenericSH, @@ -2419,6 +2446,77 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGFEComponentTransferElement, nsIDOMSVGFEComponentTransferElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEComponentTransferElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEFuncAElement, nsIDOMSVGFEFuncAElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEFuncAElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEFuncBElement, nsIDOMSVGFEFuncBElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEFuncBElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEFuncGElement, nsIDOMSVGFEFuncGElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEFuncGElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEFuncRElement, nsIDOMSVGFEFuncRElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEFuncRElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEGaussianBlurElement, nsIDOMSVGFEGaussianBlurElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEGaussianBlurElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + 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) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEMergeNodeElement, nsIDOMSVGFEMergeNodeElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEMergeNodeElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEOffsetElement, nsIDOMSVGFEOffsetElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEOffsetElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFEUnimplementedMOZElement, nsIDOMSVGFEUnimplementedMOZElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEUnimplementedMOZElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGFilterElement, nsIDOMSVGFilterElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGGElement, nsIDOMSVGGElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGGElement) DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES @@ -2563,6 +2661,10 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGAnimatedInteger, nsIDOMSVGAnimatedInteger) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedInteger) + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGAnimatedLength, nsIDOMSVGAnimatedLength) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedLength) DOM_CLASSINFO_MAP_END diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 03c94b8502c..20018f65c22 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -222,6 +222,8 @@ nsresult NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame); nsresult NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parent, nsIFrame** aNewFrame); +nsresult +NS_NewSVGFilterFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame** newFrame); #endif #include "nsIDocument.h" @@ -7310,6 +7312,9 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsFrameConstructorState& aState, else if (aTag == nsSVGAtoms::textPath) { rv = NS_NewSVGTextPathFrame(mPresShell, aContent, aParentFrame, &newFrame); } + else if (aTag == nsSVGAtoms::filter) { + rv = NS_NewSVGFilterFrame(mPresShell, aContent, &newFrame); + } if (newFrame == nsnull) { // Either we have an unknown tag, or construction of a frame diff --git a/mozilla/layout/base/nsLayoutAtomList.h b/mozilla/layout/base/nsLayoutAtomList.h index d2e0a7691d9..a064d985404 100644 --- a/mozilla/layout/base/nsLayoutAtomList.h +++ b/mozilla/layout/base/nsLayoutAtomList.h @@ -261,6 +261,7 @@ LAYOUT_ATOM(svgCircleFrame,"SVGCircleFrame") LAYOUT_ATOM(svgClipPathFrame,"SVGClipPathFrame") LAYOUT_ATOM(svgDefsFrame,"SVGDefsFrame") LAYOUT_ATOM(svgEllipseFrame,"SVGEllipseFrame") +LAYOUT_ATOM(svgFilterFrame,"SVGFilterFrame") #ifdef MOZ_SVG_FOREIGNOBJECT LAYOUT_ATOM(svgForeignObjectFrame,"SVGForeignObjectFrame") #endif diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index d6d3af604a8..ded9d0a48a1 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -4411,6 +4411,8 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode, case eCSSProperty_fill_rule: return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kFillRuleKTable); + case eCSSProperty_filter: + return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull); case eCSSProperty_marker_end: case eCSSProperty_marker_mid: case eCSSProperty_marker_start: diff --git a/mozilla/layout/style/nsCSSPropList.h b/mozilla/layout/style/nsCSSPropList.h index b84c389f7bd..7e09021ff7b 100644 --- a/mozilla/layout/style/nsCSSPropList.h +++ b/mozilla/layout/style/nsCSSPropList.h @@ -470,6 +470,7 @@ CSS_PROP_SVGRESET(dominant-baseline, dominant_baseline, DominantBaseline, SVG, m CSS_PROP_SVG(fill, fill, Fill, SVG, mFill, eCSSType_Value, nsnull) CSS_PROP_SVG(fill-opacity, fill_opacity, FillOpacity, SVG, mFillOpacity, eCSSType_Value, nsnull) CSS_PROP_SVG(fill-rule, fill_rule, FillRule, SVG, mFillRule, eCSSType_Value, kFillRuleKTable) +CSS_PROP_SVGRESET(filter, filter, Filter, SVG, mFilter, eCSSType_Value, nsnull) CSS_PROP_SHORTHAND(marker, marker, Marker) CSS_PROP_SVG(marker-end, marker_end, MarkerEnd, SVG, mMarkerEnd, eCSSType_Value, nsnull) CSS_PROP_SVG(marker-mid, marker_mid, MarkerMid, SVG, mMarkerMid, eCSSType_Value, nsnull) diff --git a/mozilla/layout/style/nsCSSStruct.cpp b/mozilla/layout/style/nsCSSStruct.cpp index 4044483654d..febab6f354b 100644 --- a/mozilla/layout/style/nsCSSStruct.cpp +++ b/mozilla/layout/style/nsCSSStruct.cpp @@ -1211,6 +1211,7 @@ nsCSSSVG::nsCSSSVG(const nsCSSSVG& aCopy) mFill(aCopy.mFill), mFillOpacity(aCopy.mFillOpacity), mFillRule(aCopy.mFillRule), + mFilter(aCopy.mFilter), mMarkerEnd(aCopy.mMarkerEnd), mMarkerMid(aCopy.mMarkerMid), mMarkerStart(aCopy.mMarkerStart), @@ -1252,6 +1253,7 @@ void nsCSSSVG::List(FILE* out, PRInt32 aIndent) const mFill.AppendToString(buffer, eCSSProperty_fill); mFillOpacity.AppendToString(buffer, eCSSProperty_fill_opacity); mFillRule.AppendToString(buffer, eCSSProperty_fill_rule); + mFilter.AppendToString(buffer, eCSSProperty_filter); mMarkerEnd.AppendToString(buffer, eCSSProperty_marker_end); mMarkerMid.AppendToString(buffer, eCSSProperty_marker_mid); mMarkerStart.AppendToString(buffer, eCSSProperty_marker_start); diff --git a/mozilla/layout/style/nsCSSStruct.h b/mozilla/layout/style/nsCSSStruct.h index 7060eb8d9a3..e18a3817f25 100644 --- a/mozilla/layout/style/nsCSSStruct.h +++ b/mozilla/layout/style/nsCSSStruct.h @@ -584,6 +584,7 @@ struct nsCSSSVG : public nsCSSStruct { nsCSSValue mFill; nsCSSValue mFillOpacity; nsCSSValue mFillRule; + nsCSSValue mFilter; nsCSSValue mMarkerEnd; nsCSSValue mMarkerMid; nsCSSValue mMarkerStart; diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index 9c2fbbd3273..447eeeb5505 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -5001,6 +5001,15 @@ nsRuleNode::ComputeSVGResetData(nsStyleStruct* aStartStruct, svgReset->mDominantBaseline = parentSVGReset->mDominantBaseline; } + // filter: url, none, inherit + if (eCSSUnit_URL == SVGData.mFilter.GetUnit()) { + svgReset->mFilter = SVGData.mFilter.GetURLValue(); + } else if (eCSSUnit_None == SVGData.mFilter.GetUnit()) { + svgReset->mFilter = nsnull; + } else if (eCSSUnit_Inherit == SVGData.mFilter.GetUnit()) { + inherited = PR_TRUE; + svgReset->mFilter = parentSVGReset->mFilter; + } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the diff --git a/mozilla/layout/style/nsStyleContext.cpp b/mozilla/layout/style/nsStyleContext.cpp index 2938a0c05e7..c6afa7e2ed2 100644 --- a/mozilla/layout/style/nsStyleContext.cpp +++ b/mozilla/layout/style/nsStyleContext.cpp @@ -932,8 +932,9 @@ void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out, else fprintf(out, "%ld ", (long)svgReset->mStopColor.mPaint.mColor); - fprintf(out, "%s %f %d\" />\n", + fprintf(out, "%s %s %f %d\" />\n", URICString(svgReset->mClipPath).get(), + URICString(svgReset->mFilter).get(), svgReset->mStopOpacity, (int)svgReset->mDominantBaseline); #endif diff --git a/mozilla/layout/style/nsStyleStruct.cpp b/mozilla/layout/style/nsStyleStruct.cpp index 4b19d9d836b..6a338940a24 100644 --- a/mozilla/layout/style/nsStyleStruct.cpp +++ b/mozilla/layout/style/nsStyleStruct.cpp @@ -834,6 +834,7 @@ nsStyleSVGReset::nsStyleSVGReset() mStopColor.mType = eStyleSVGPaintType_Color; mStopColor.mPaint.mColor = NS_RGB(0,0,0); mClipPath = nsnull; + mFilter = nsnull; mStopOpacity = 1.0f; mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO; } @@ -846,6 +847,7 @@ nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource) { mStopColor = aSource.mStopColor; mClipPath = aSource.mClipPath; + mFilter = aSource.mFilter; mStopOpacity = aSource.mStopOpacity; mDominantBaseline = aSource.mDominantBaseline; } @@ -854,6 +856,7 @@ nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) cons { if (mStopColor != aOther.mStopColor || !EqualURIs(mClipPath, aOther.mClipPath) || + !EqualURIs(mFilter, aOther.mFilter) || mStopOpacity != aOther.mStopOpacity || mDominantBaseline != aOther.mDominantBaseline) return NS_STYLE_HINT_VISUAL; diff --git a/mozilla/layout/style/nsStyleStruct.h b/mozilla/layout/style/nsStyleStruct.h index 1b937f6fa79..85fd7adaaca 100644 --- a/mozilla/layout/style/nsStyleStruct.h +++ b/mozilla/layout/style/nsStyleStruct.h @@ -1338,7 +1338,10 @@ struct nsStyleSVGReset : public nsStyleStruct { nsStyleSVGPaint mStopColor; // [reset] nsCOMPtr mClipPath; // [reset] + nsCOMPtr mFilter; // [reset] + float mStopOpacity; // [reset] + PRUint8 mDominantBaseline; // [reset] see nsStyleConsts.h }; #endif diff --git a/mozilla/layout/svg/base/src/Makefile.in b/mozilla/layout/svg/base/src/Makefile.in index 08cbcb4e646..5d373010f21 100644 --- a/mozilla/layout/svg/base/src/Makefile.in +++ b/mozilla/layout/svg/base/src/Makefile.in @@ -71,6 +71,7 @@ CPPSRCS = \ nsSVGClipPathFrame.cpp \ nsSVGDefsFrame.cpp \ nsSVGEllipseFrame.cpp \ + nsSVGFilterFrame.cpp \ nsSVGGFrame.cpp \ nsSVGGenericContainerFrame.cpp \ nsSVGGlyphFrame.cpp \ @@ -102,7 +103,10 @@ include $(topsrcdir)/config/config.mk # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -EXPORTS = nsSVGUtils.h +EXPORTS = \ + nsSVGUtils.h \ + nsSVGFilterInstance.h \ + $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/mozilla/layout/svg/base/src/nsISVGChildFrame.h b/mozilla/layout/svg/base/src/nsISVGChildFrame.h index 317bf342363..1990a894cd8 100644 --- a/mozilla/layout/svg/base/src/nsISVGChildFrame.h +++ b/mozilla/layout/svg/base/src/nsISVGChildFrame.h @@ -47,10 +47,11 @@ class nsISVGRendererCanvas; class nsPresContext; class nsIDOMSVGRect; +class nsIDOMSVGMatrix; struct nsRect; #define NS_ISVGCHILDFRAME_IID \ -{ 0x13c16e09, 0x049d, 0x407c, { 0x91, 0xf2, 0xf0, 0xbc, 0xf1, 0xb3, 0xab, 0x81 } } +{ 0xe3280ee5, 0x0980, 0x45f4, { 0xb4, 0x84, 0xc4, 0x11, 0xbc, 0x36, 0xcd, 0xda } } class nsISVGChildFrame : public nsISupports { public: @@ -60,8 +61,12 @@ public: // 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 - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)=0; + // 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; // Check if this frame or children contain the given point, // specified in device pixels relative to the origin of the outer @@ -76,14 +81,25 @@ public: NS_IMETHOD_(already_AddRefed) GetCoveredRegion()=0; NS_IMETHOD InitialUpdate()=0; - NS_IMETHOD NotifyCanvasTMChanged()=0; + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation)=0; NS_IMETHOD NotifyRedrawSuspended()=0; NS_IMETHOD NotifyRedrawUnsuspended()=0; + // Set whether we should stop multiplying matrices when building up + // the current transformation matrix at this frame. NS_IMETHOD SetMatrixPropagation(PRBool aPropagate)=0; + // Set the current transformation matrix to a particular matrix. + // Value is only used if matrix propogation is prevented + // (SetMatrixPropagation()). nsnull aCTM means identity transform. + NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM)=0; + // 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; }; #endif // __NS_ISVGCHILDFRAME_H__ diff --git a/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp b/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp index d1add209bc8..e73002e35a4 100644 --- a/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp @@ -154,7 +154,7 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas, mClipParent = aParent, mClipParentMatrix = aMatrix; - NotifyCanvasTMChanged(); + NotifyCanvasTMChanged(PR_TRUE); rv = canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP); if (NS_FAILED(rv)) @@ -165,7 +165,7 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas, nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->PaintSVG(canvas, dirty); + SVGFrame->PaintSVG(canvas, dirty, PR_TRUE); } } diff --git a/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp b/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp index b6d34a0c2df..2ccdd5cbcf5 100644 --- a/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp @@ -228,7 +228,7 @@ nsSVGDefsFrame::DidModifySVGObservable (nsISVGValue* observable, nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(PR_FALSE); } return NS_OK; } @@ -238,7 +238,9 @@ nsSVGDefsFrame::DidModifySVGObservable (nsISVGValue* observable, // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGDefsFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGDefsFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { // defs don't paint @@ -277,7 +279,7 @@ nsSVGDefsFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGDefsFrame::NotifyCanvasTMChanged() +nsSVGDefsFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; @@ -287,7 +289,7 @@ nsSVGDefsFrame::NotifyCanvasTMChanged() nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(suppressInvalidation); } } return NS_OK; diff --git a/mozilla/layout/svg/base/src/nsSVGDefsFrame.h b/mozilla/layout/svg/base/src/nsSVGDefsFrame.h index 47f691751d7..a7a44f4ad2d 100644 --- a/mozilla/layout/svg/base/src/nsSVGDefsFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGDefsFrame.h @@ -108,15 +108,22 @@ public: // implementation inherited from nsSupportsWeakReference // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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: nsISVGOuterSVGFrame *GetOuterSVGFrame(); diff --git a/mozilla/layout/svg/base/src/nsSVGFilterFrame.cpp b/mozilla/layout/svg/base/src/nsSVGFilterFrame.cpp new file mode 100644 index 00000000000..a0512902cee --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -0,0 +1,743 @@ +/* -*- 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): + * + * 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 "nsSVGFilterFrame.h" +#include "nsSVGFilterInstance.h" +#include "nsIDOMDocument.h" +#include "nsIDOMElement.h" +#include "nsIDocument.h" +#include "nsISVGValue.h" +#include "nsIDOMSVGFilterElement.h" +#include "nsIDOMSVGAnimatedLength.h" +#include "nsISVGValueUtils.h" +#include "nsISVGGeometrySource.h" +#include "nsSVGMatrix.h" +#include "nsISVGRenderer.h" +#include "nsISVGRendererCanvas.h" +#include "nsISVGOuterSVGFrame.h" +#include "nsISVGFilter.h" +#include "nsSVGLength.h" +#include "nsIDOMSVGSVGElement.h" +#include "nsINameSpaceManager.h" +#include "nsSVGAtoms.h" +#include "nsSVGDefsFrame.h" +#include "nsIDOMSVGLength.h" +#include "nsIDOMSVGRect.h" +#include "nsIDOMSVGAnimatedEnum.h" +#include "nsSVGValue.h" +#include "nsSVGPoint.h" +#include "nsIDOMSVGAnimatedInteger.h" +#include "nsSVGUtils.h" + +class nsSVGFilterFrame : public nsSVGDefsFrame, + public nsSVGValue, + public nsISVGFilterFrame +{ +protected: + friend nsresult + NS_NewSVGFilterFrame(nsIPresShell* aPresShell, + nsIContent* aContent, + nsIFrame** aNewFrame); + + virtual ~nsSVGFilterFrame(); + NS_IMETHOD InitSVG(); + +public: + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + // nsISVGFilterFrame interface: + NS_IMETHOD FilterPaint(nsISVGRendererCanvas *aCanvas, + nsISVGChildFrame *aTarget); + NS_IMETHOD GetInvalidationRegion(nsIFrame *aTarget, + nsISVGRendererRegion **aRegion); + + // nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString &aValue) { return NS_OK; } + NS_IMETHOD GetValueString(nsAString& aValue) { return NS_ERROR_NOT_IMPLEMENTED; } + + // nsISVGValueObserver interface: + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType); + NS_IMETHOD DidModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType); + + /** + * Get the "type" of the frame + * + * @see nsLayoutAtoms::svgFilterFrame + */ + virtual nsIAtom* GetType() const; + +private: + // implementation helpers + void FilterFailCleanup(nsISVGRendererCanvas *aCanvas, + nsISVGChildFrame *aTarget); + +private: + nsCOMPtr mX; + nsCOMPtr mY; + nsCOMPtr mWidth; + nsCOMPtr mHeight; + nsCOMPtr mFilterUnits; + nsCOMPtr mPrimitiveUnits; + nsCOMPtr mFilterResX; + nsCOMPtr mFilterResY; +}; + +NS_INTERFACE_MAP_BEGIN(nsSVGFilterFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGValue) + NS_INTERFACE_MAP_ENTRY(nsISVGFilterFrame) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue) +NS_INTERFACE_MAP_END_INHERITING(nsSVGDefsFrame) + +nsresult +NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame) +{ + *aNewFrame = nsnull; + + nsSVGFilterFrame* it = new (aPresShell) nsSVGFilterFrame; + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + *aNewFrame = it; + + return NS_OK; +} + +nsresult +NS_GetSVGFilterFrame(nsISVGFilterFrame **aResult, + nsIURI *aURI, nsIContent *aContent) +{ + *aResult = nsnull; + + // Get the PresShell + nsIDocument *myDoc = aContent->GetCurrentDoc(); + if (!myDoc) { + NS_WARNING("No document for this content!"); + return NS_ERROR_FAILURE; + } + nsIPresShell *aPresShell = myDoc->GetShellAt(0); + + // Get the URI Spec + nsCAutoString uriSpec; + aURI->GetSpec(uriSpec); + + // Find the referenced frame + nsIFrame *filter; + if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&filter, + uriSpec, aContent, aPresShell))) + return NS_ERROR_FAILURE; + + nsIAtom* frameType = filter->GetType(); + if (frameType != nsLayoutAtoms::svgFilterFrame) + return NS_ERROR_FAILURE; + + *aResult = (nsSVGFilterFrame *)filter; + return NS_OK; +} + +nsSVGFilterFrame::~nsSVGFilterFrame() +{ + WillModify(); + // Notify the world that we're dying + DidModify(mod_die); + + NS_REMOVE_SVGVALUE_OBSERVER(mX); + NS_REMOVE_SVGVALUE_OBSERVER(mY); + NS_REMOVE_SVGVALUE_OBSERVER(mWidth); + NS_REMOVE_SVGVALUE_OBSERVER(mHeight); + NS_REMOVE_SVGVALUE_OBSERVER(mFilterUnits); + NS_REMOVE_SVGVALUE_OBSERVER(mPrimitiveUnits); + NS_REMOVE_SVGVALUE_OBSERVER(mFilterResX); + NS_REMOVE_SVGVALUE_OBSERVER(mFilterResY); + NS_REMOVE_SVGVALUE_OBSERVER(mContent); +} + +//---------------------------------------------------------------------- +// nsISVGValueObserver methods: +NS_IMETHODIMP +nsSVGFilterFrame::WillModifySVGObservable(nsISVGValue* observable, + modificationType aModType) +{ + WillModify(aModType); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFilterFrame::DidModifySVGObservable(nsISVGValue* observable, + nsISVGValue::modificationType aModType) +{ + // Something we depend on was modified -- pass it on! + DidModify(aModType); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFilterFrame::InitSVG() +{ + nsresult rv = nsSVGDefsFrame::InitSVG(); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr filter = do_QueryInterface(mContent); + NS_ASSERTION(filter, "wrong content element"); + + { + nsCOMPtr length; + filter->GetX(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mX)); + NS_ASSERTION(mX, "no X"); + if (!mX) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mX); + } + + { + nsCOMPtr length; + filter->GetY(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mY)); + NS_ASSERTION(mY, "no Y"); + if (!mY) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mY); + } + + { + nsCOMPtr length; + filter->GetWidth(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mWidth)); + NS_ASSERTION(mWidth, "no Width"); + if (!mWidth) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mWidth); + } + + { + nsCOMPtr length; + filter->GetHeight(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mHeight)); + NS_ASSERTION(mHeight, "no Height"); + if (!mHeight) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mHeight); + } + + filter->GetFilterUnits(getter_AddRefs(mFilterUnits)); + NS_ADD_SVGVALUE_OBSERVER(mFilterUnits); + + filter->GetPrimitiveUnits(getter_AddRefs(mPrimitiveUnits)); + NS_ADD_SVGVALUE_OBSERVER(mPrimitiveUnits); + + filter->GetFilterResX(getter_AddRefs(mFilterResX)); + NS_ADD_SVGVALUE_OBSERVER(mFilterResX); + + filter->GetFilterResY(getter_AddRefs(mFilterResY)); + NS_ADD_SVGVALUE_OBSERVER(mFilterResY); + + NS_ADD_SVGVALUE_OBSERVER(mContent); + + return NS_OK; +} + +void +nsSVGFilterFrame::FilterFailCleanup(nsISVGRendererCanvas *aCanvas, + nsISVGChildFrame *aTarget) +{ + aTarget->SetOverrideCTM(nsnull); + aTarget->SetMatrixPropagation(PR_TRUE); + aTarget->NotifyCanvasTMChanged(PR_TRUE); + nsRect dummyRect; + aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE); +} + +NS_IMETHODIMP +nsSVGFilterFrame::FilterPaint(nsISVGRendererCanvas *aCanvas, + nsISVGChildFrame *aTarget) +{ + nsCOMPtr aFilter = do_QueryInterface(mContent); + NS_ASSERTION(aFilter, "Wrong content element (not filter)"); + + PRBool unimplementedFilter = PR_FALSE; + PRUint32 requirements = 0; + PRUint32 count = mContent->GetChildCount(); + for (PRUint32 i=0; iGetChildAt(i); + + nsCOMPtr filter = do_QueryInterface(child); + if (filter) { + PRUint32 tmp; + filter->GetRequirements(&tmp); + requirements |= tmp; + } + + nsCOMPtr unimplemented; + unimplemented = do_QueryInterface(child); + if (unimplemented) + unimplementedFilter = PR_TRUE; + } + + // check for source requirements or filter elements that we don't support yet + if (requirements & ~(NS_FE_SOURCEGRAPHIC | NS_FE_SOURCEALPHA) || + unimplementedFilter) { +#ifdef DEBUG_tor + if (requirements & ~(NS_FE_SOURCEGRAPHIC | NS_FE_SOURCEALPHA)) + fprintf(stderr, "FilterFrame: unimplemented source requirement\n"); + if (unimplementedFilter) + fprintf(stderr, "FilterFrame: unimplemented filter element\n"); +#endif + nsRect dummyRect; + aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE); + return NS_OK; + } + + nsCOMPtr ctm; + + nsISVGContainerFrame *aContainer; + CallQueryInterface(aTarget, &aContainer); + if (aContainer) + ctm = aContainer->GetCanvasTM(); + else { + nsISVGGeometrySource *aSource; + CallQueryInterface(aTarget, &aSource); + if (aSource) + aSource->GetCanvasTM(getter_AddRefs(ctm)); + } + + float s1, s2; + ctm->GetA(&s1); + ctm->GetD(&s2); +#ifdef DEBUG_tor + fprintf(stderr, "scales: %f %f\n", s1, s2); +#endif + + nsIFrame *frame; + CallQueryInterface(aTarget, &frame); + nsIContent *target = frame->GetContent(); + + aTarget->SetMatrixPropagation(PR_FALSE); + aTarget->NotifyCanvasTMChanged(PR_TRUE); + + PRUint16 type; + mFilterUnits->GetAnimVal(&type); + + float x, y, width, height; + nsCOMPtr bbox; + aTarget->GetBBox(getter_AddRefs(bbox)); + + if (type == nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX) { + bbox->GetX(&x); + x += nsSVGUtils::ObjectSpace(bbox, mX, nsSVGUtils::X); + bbox->GetY(&y); + y += nsSVGUtils::ObjectSpace(bbox, mY, nsSVGUtils::Y); + width = nsSVGUtils::ObjectSpace(bbox, mWidth, nsSVGUtils::X); + height = nsSVGUtils::ObjectSpace(bbox, mHeight, nsSVGUtils::Y); + } else { + x = nsSVGUtils::UserSpace(target, mX, nsSVGUtils::X); + y = nsSVGUtils::UserSpace(target, mY, nsSVGUtils::Y); + width = nsSVGUtils::UserSpace(target, mWidth, nsSVGUtils::X); + height = nsSVGUtils::UserSpace(target, mHeight, nsSVGUtils::Y); + } + + PRInt32 filterResX = PRInt32(s1 * width + 0.5); + PRInt32 filterResY = PRInt32(s2 * height + 0.5); + + if (mContent->HasAttr(kNameSpaceID_None, nsSVGAtoms::filterRes)) { + mFilterResX->GetAnimVal(&filterResX); + mFilterResY->GetAnimVal(&filterResY); + } + + // filterRes = 0 disables rendering, < 0 is error + if (filterResX <= 0.0f || filterResY <= 0.0f) + return NS_OK; + +#ifdef DEBUG_tor + fprintf(stderr, "filter bbox: %f,%f %fx%f\n", x, y, width, height); + fprintf(stderr, "filterRes: %u %u\n", filterResX, filterResY); +#endif + + nsCOMPtr filterTransform; + NS_NewSVGMatrix(getter_AddRefs(filterTransform), + filterResX/width, 0.0f, + 0.0f, filterResY/height, + -x*filterResX/width, -y*filterResY/height); + aTarget->SetOverrideCTM(filterTransform); + aTarget->NotifyCanvasTMChanged(PR_TRUE); + + // paint the target geometry + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + nsCOMPtr renderer; + nsCOMPtr surface; + outerSVGFrame->GetRenderer(getter_AddRefs(renderer)); + renderer->CreateSurface(filterResX, filterResY, getter_AddRefs(surface)); + + if (!surface) { + FilterFailCleanup(aCanvas, aTarget); + return NS_OK; + } + + aCanvas->PushSurface(surface); + nsRect dummyRect; + aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE); + aCanvas->PopSurface(); + + mPrimitiveUnits->GetAnimVal(&type); + nsSVGFilterInstance instance(renderer, target, bbox, + x, y, width, height, + filterResX, filterResY, + type); + + if (requirements & NS_FE_SOURCEALPHA) { + nsCOMPtr alpha; + renderer->CreateSurface(filterResX, filterResY, getter_AddRefs(alpha)); + + if (!alpha) { + FilterFailCleanup(aCanvas, aTarget); + return NS_OK; + } + + PRUint8 *data, *alphaData; + PRUint32 length; + PRInt32 stride; + surface->Lock(); + alpha->Lock(); + surface->GetData(&data, &length, &stride); + alpha->GetData(&alphaData, &length, &stride); + + for (PRUint32 yy=0; yyUnlock(); + alpha->Unlock(); + + instance.DefineImage(NS_LITERAL_STRING("SourceAlpha"), surface); + instance.DefineRegion(NS_LITERAL_STRING("SourceAlpha"), + nsRect(0, 0, filterResX, filterResY)); + } + + // this always needs to be defined last because the default image + // for the first filter element is supposed to be SourceGraphic + instance.DefineImage(NS_LITERAL_STRING("SourceGraphic"), surface); + instance.DefineRegion(NS_LITERAL_STRING("SourceGraphic"), + nsRect(0, 0, filterResX, filterResY)); + + for (PRUint32 k=0; kGetChildAt(k); + + nsCOMPtr filter = do_QueryInterface(child); + if (filter) + rv = filter->Filter(&instance); + if (NS_FAILED(rv)) { + FilterFailCleanup(aCanvas, aTarget); + return NS_OK; + } + } + + nsCOMPtr filterResult; + instance.LookupImage(NS_LITERAL_STRING(""), getter_AddRefs(filterResult)); + + nsCOMPtr scale, fini; + NS_NewSVGMatrix(getter_AddRefs(scale), + width/filterResX, 0.0f, + 0.0f, height/filterResY, + x, y); + + ctm->Multiply(scale, getter_AddRefs(fini)); + + aCanvas->CompositeSurfaceMatrix(filterResult, fini, 1.0); + + aTarget->SetOverrideCTM(nsnull); + aTarget->SetMatrixPropagation(PR_TRUE); + aTarget->NotifyCanvasTMChanged(PR_TRUE); + + return NS_OK; +} + +NS_IMETHODIMP +nsSVGFilterFrame::GetInvalidationRegion(nsIFrame *aTarget, + nsISVGRendererRegion **aRegion) +{ + nsIContent *targetContent = aTarget->GetContent(); + nsISVGChildFrame *svg; + + nsCOMPtr ctm; + + nsISVGContainerFrame *aContainer; + CallQueryInterface(aTarget, &aContainer); + if (aContainer) + ctm = aContainer->GetCanvasTM(); + else { + nsISVGGeometrySource *source; + CallQueryInterface(aTarget, &source); + if (source) + source->GetCanvasTM(getter_AddRefs(ctm)); + } + + CallQueryInterface(aTarget, &svg); + + svg->SetMatrixPropagation(PR_FALSE); + svg->NotifyCanvasTMChanged(PR_TRUE); + + PRUint16 type; + mFilterUnits->GetAnimVal(&type); + + float x, y, width, height; + nsCOMPtr bbox; + svg->GetBBox(getter_AddRefs(bbox)); + + if (type == nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX) { + bbox->GetX(&x); + x += nsSVGUtils::ObjectSpace(bbox, mX, nsSVGUtils::X); + bbox->GetY(&y); + y += nsSVGUtils::ObjectSpace(bbox, mY, nsSVGUtils::Y); + width = nsSVGUtils::ObjectSpace(bbox, mWidth, nsSVGUtils::X); + height = nsSVGUtils::ObjectSpace(bbox, mHeight, nsSVGUtils::Y); + } else { + x = nsSVGUtils::UserSpace(targetContent, mX, nsSVGUtils::X); + y = nsSVGUtils::UserSpace(targetContent, mY, nsSVGUtils::Y); + width = nsSVGUtils::UserSpace(targetContent, mWidth, nsSVGUtils::X); + height = nsSVGUtils::UserSpace(targetContent, mHeight, nsSVGUtils::Y); + } + + svg->SetMatrixPropagation(PR_TRUE); + svg->NotifyCanvasTMChanged(PR_TRUE); + +#ifdef DEBUG_tor + fprintf(stderr, "invalidate box: %f,%f %fx%f\n", x, y, width, height); +#endif + + // transform back + float xx[4], yy[4]; + xx[0] = x; yy[0] = y; + xx[1] = x + width; yy[1] = y; + xx[2] = x + width; yy[2] = y + height; + xx[3] = x; yy[3] = y + height; + + nsSVGUtils::TransformPoint(ctm, &xx[0], &yy[0]); + nsSVGUtils::TransformPoint(ctm, &xx[1], &yy[1]); + nsSVGUtils::TransformPoint(ctm, &xx[2], &yy[2]); + nsSVGUtils::TransformPoint(ctm, &xx[3], &yy[3]); + + float xmin, xmax, ymin, ymax; + xmin = xmax = xx[0]; + ymin = ymax = yy[0]; + for (int i=1; i<4; i++) { + if (xx[i] < xmin) + xmin = xx[i]; + if (yy[i] < ymin) + ymin = yy[i]; + if (xx[i] > xmax) + xmax = xx[i]; + if (yy[i] > ymax) + ymax = yy[i]; + } + +#ifdef DEBUG_tor + fprintf(stderr, "xform bound: %f %f %f %f\n", xmin, ymin, xmax, ymax); +#endif + + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + nsCOMPtr renderer; + outerSVGFrame->GetRenderer(getter_AddRefs(renderer)); + renderer->CreateRectRegion(xmin, ymin, xmax - xmin, ymax - ymin, aRegion); + + return NS_OK; +} + +nsIAtom * +nsSVGFilterFrame::GetType() const +{ + return nsLayoutAtoms::svgFilterFrame; +} + +// ---------------------------------------------------------------- +// nsSVGFilterInstance + +float +nsSVGFilterInstance::GetPrimitiveX(nsIDOMSVGLength *aLength) +{ + float value; + if (mPrimitiveUnits == nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX) + value = nsSVGUtils::ObjectSpace(mTargetBBox, aLength, nsSVGUtils::X); + else + value = nsSVGUtils::UserSpace(mTarget, aLength, nsSVGUtils::X); + + return value * mFilterResX / mFilterWidth; +} + +float +nsSVGFilterInstance::GetPrimitiveY(nsIDOMSVGLength *aLength) +{ + float value; + if (mPrimitiveUnits == nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX) + value = nsSVGUtils::ObjectSpace(mTargetBBox, aLength, nsSVGUtils::Y); + else + value = nsSVGUtils::UserSpace(mTarget, aLength, nsSVGUtils::Y); + + return value * mFilterResY / mFilterHeight; +} + +float +nsSVGFilterInstance::GetPrimitiveXY(nsIDOMSVGLength *aLength) +{ + float value; + if (mPrimitiveUnits == nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX) + value = nsSVGUtils::ObjectSpace(mTargetBBox, aLength, nsSVGUtils::XY); + else + value = nsSVGUtils::UserSpace(mTarget, aLength, nsSVGUtils::XY); + + return value * + sqrt(float(mFilterResX * mFilterResX + mFilterResY * mFilterResY)) / + sqrt(mFilterWidth * mFilterWidth + mFilterHeight * mFilterHeight); +} + +void +nsSVGFilterInstance::GetFilterSubregion( + nsIDOMSVGFilterPrimitiveStandardAttributes *aFilter, + nsRect defaultRegion, + nsRect *result) +{ + nsCOMPtr svgX, svgY, svgWidth, svgHeight; + nsCOMPtr val; + aFilter->GetX(getter_AddRefs(val)); + val->GetBaseVal(getter_AddRefs(svgX)); + aFilter->GetY(getter_AddRefs(val)); + val->GetBaseVal(getter_AddRefs(svgY)); + aFilter->GetWidth(getter_AddRefs(val)); + val->GetBaseVal(getter_AddRefs(svgWidth)); + aFilter->GetHeight(getter_AddRefs(val)); + val->GetBaseVal(getter_AddRefs(svgHeight)); + + float x, y, width, height; + + if (mPrimitiveUnits == + nsIDOMSVGFilterElement::SVG_FUNITS_OBJECTBOUNDINGBOX) { + x = nsSVGUtils::ObjectSpace(mTargetBBox, svgX, nsSVGUtils::X); + y = nsSVGUtils::ObjectSpace(mTargetBBox, svgY, nsSVGUtils::Y); + width = nsSVGUtils::ObjectSpace(mTargetBBox, svgWidth, nsSVGUtils::X); + height = nsSVGUtils::ObjectSpace(mTargetBBox, svgHeight, nsSVGUtils::Y); + } else { + x = nsSVGUtils::UserSpace(mTarget, svgX, nsSVGUtils::X); + y = nsSVGUtils::UserSpace(mTarget, svgY, nsSVGUtils::Y); + width = nsSVGUtils::UserSpace(mTarget, svgWidth, nsSVGUtils::X); + height = nsSVGUtils::UserSpace(mTarget, svgHeight, nsSVGUtils::Y); + } + +#ifdef DEBUG_tor + fprintf(stderr, "GFS[1]: %f %f %f %f\n", x, y, width, height); +#endif + + nsRect filter, region; + + filter.x = 0; + filter.y = 0; + filter.width = mFilterResX; + filter.height = mFilterResY; + + region.x = (x - mFilterX) * mFilterResX / mFilterWidth; + region.y = (y - mFilterY) * mFilterResY / mFilterHeight; + region.width = width * mFilterResX / mFilterWidth; + region.height = height * mFilterResY / mFilterHeight; + +#ifdef DEBUG_tor + fprintf(stderr, "GFS[2]: %d %d %d %d\n", + region.x, region.y, region.width, region.height); +#endif + + nsCOMPtr content = do_QueryInterface(aFilter); + if (!content->HasAttr(kNameSpaceID_None, nsSVGAtoms::x)) + region.x = defaultRegion.x; + if (!content->HasAttr(kNameSpaceID_None, nsSVGAtoms::y)) + region.y = defaultRegion.y; + if (!content->HasAttr(kNameSpaceID_None, nsSVGAtoms::width)) + region.width = defaultRegion.width; + if (!content->HasAttr(kNameSpaceID_None, nsSVGAtoms::height)) + region.height = defaultRegion.height; + + result->IntersectRect(filter, region); + +#ifdef DEBUG_tor + fprintf(stderr, "GFS[3]: %d %d %d %d\n", + result->x, result->y, result->width, result->height); +#endif +} + +void +nsSVGFilterInstance::GetImage(nsISVGRendererSurface **result) +{ + mRenderer->CreateSurface(mFilterResX, mFilterResY, result); +} + +void +nsSVGFilterInstance::LookupImage(const nsAString &aName, + nsISVGRendererSurface **aImage) +{ + if (aName.IsEmpty()) { + *aImage = mLastImage; + NS_IF_ADDREF(*aImage); + } else + mImageDictionary.Get(aName, aImage); +} + +void +nsSVGFilterInstance::DefineImage(const nsAString &aName, + nsISVGRendererSurface *aImage) +{ + mImageDictionary.Put(aName, aImage); + mLastImage = aImage; +} + +void +nsSVGFilterInstance::LookupRegion(const nsAString &aName, + nsRect *aRect) +{ + if (aName.IsEmpty()) + *aRect = mLastRegion; + else + mRegionDictionary.Get(aName, aRect); +} + +void +nsSVGFilterInstance::DefineRegion(const nsAString &aName, + nsRect aRect) +{ + mRegionDictionary.Put(aName, aRect); + mLastRegion = aRect; +} diff --git a/mozilla/layout/svg/base/src/nsSVGFilterFrame.h b/mozilla/layout/svg/base/src/nsSVGFilterFrame.h new file mode 100644 index 00000000000..8ee4c1d63cb --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGFilterFrame.h @@ -0,0 +1,68 @@ +/* -*- 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): + * + * 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 ***** */ + +#ifndef __NS_SVGFILTERFRAME_H__ +#define __NS_SVGFILTERFRAME_H__ + +#include "nsISupports.h" + +class nsISVGRendererCanvas; +class nsISVGChildFrame; +class nsIURI; +class nsIContent; +class nsISVGRendererRegion; +class nsIFrame; + +#define NS_ISVGFILTERFRAME_IID \ +{0x482c56ef, 0x9ff9, 0x49ef, {0xa3, 0xa3, 0x64, 0x46, 0x5c, 0xfc, 0xf5, 0x1d}} + +class nsISVGFilterFrame : public nsISupports { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISVGFILTERFRAME_IID) + + NS_IMETHOD FilterPaint(nsISVGRendererCanvas *aCanvas, + nsISVGChildFrame *aTarget) = 0; + + NS_IMETHOD GetInvalidationRegion(nsIFrame *aTarget, + nsISVGRendererRegion **aRegion) = 0; +}; + +nsresult +NS_GetSVGFilterFrame(nsISVGFilterFrame **aResult, + nsIURI *aURI, + nsIContent *aContent); + +#endif diff --git a/mozilla/layout/svg/base/src/nsSVGFilterInstance.h b/mozilla/layout/svg/base/src/nsSVGFilterInstance.h new file mode 100644 index 00000000000..150c15c4f24 --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGFilterInstance.h @@ -0,0 +1,99 @@ +/* -*- 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): + * + * 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 ***** */ + +#ifndef __NS_SVGFILTERINSTANCE_H__ +#define __NS_SVGFILTERINSTANCE_H__ + +#include "nsIDOMSVGLength.h" +#include "nsIDOMSVGRect.h" +#include "nsIDOMSVGAnimatedEnum.h" +#include "nsISVGRendererSurface.h" +#include "nsInterfaceHashtable.h" +#include "nsDataHashtable.h" +#include "nsISVGRenderer.h" +#include "nsIDOMSVGFilters.h" +#include "nsRect.h" + +class nsSVGFilterInstance +{ +public: + float GetPrimitiveX(nsIDOMSVGLength *aLength); + float GetPrimitiveY(nsIDOMSVGLength *aLength); + float GetPrimitiveXY(nsIDOMSVGLength *aLength); + + void GetFilterSubregion(nsIDOMSVGFilterPrimitiveStandardAttributes *aFilter, + nsRect defaultRegion, + nsRect *result); + + void GetImage(nsISVGRendererSurface **result); + void LookupImage(const nsAString &aName, nsISVGRendererSurface **aImage); + void DefineImage(const nsAString &aName, nsISVGRendererSurface *aImage); + void LookupRegion(const nsAString &aName, nsRect *aRect); + void DefineRegion(const nsAString &aName, nsRect aRect); + + nsSVGFilterInstance(nsISVGRenderer *aRenderer, + nsIContent *aTarget, + nsIDOMSVGRect *aTargetBBox, + float aFilterX, float aFilterY, + float aFilterWidth, float aFilterHeight, + PRUint32 aFilterResX, PRUint32 aFilterResY, + PRUint16 aPrimitiveUnits) : + mRenderer(aRenderer), + mTarget(aTarget), + mTargetBBox(aTargetBBox), + mFilterX(aFilterX), mFilterY(aFilterY), + mFilterWidth(aFilterWidth), mFilterHeight(aFilterHeight), + mFilterResX(aFilterResX), mFilterResY(aFilterResY), + mPrimitiveUnits(aPrimitiveUnits) { + mImageDictionary.Init(); + mRegionDictionary.Init(); + } + +private: + nsCOMPtr mRenderer; + nsCOMPtr mTarget; + nsCOMPtr mTargetBBox; + float mFilterX, mFilterY, mFilterWidth, mFilterHeight; + PRUint32 mFilterResX, mFilterResY; + PRUint16 mPrimitiveUnits; + + nsInterfaceHashtable mImageDictionary; + nsDataHashtable mRegionDictionary; + nsCOMPtr mLastImage; + nsRect mLastRegion; +}; + +#endif diff --git a/mozilla/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/mozilla/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index be97c2ac03f..78e36dd0fde 100644 --- a/mozilla/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -138,14 +138,17 @@ public: // implementation inherited from nsSupportsWeakReference // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate); + NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM); NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval); // nsISVGContainerFrame interface: @@ -169,6 +172,7 @@ protected: nsCOMPtr mHeight; nsCOMPtr mCanvasTM; PRBool mPropagateTransform; + nsCOMPtr mOverrideCTM; }; //---------------------------------------------------------------------- @@ -467,7 +471,9 @@ nsSVGForeignObjectFrame::DidModifySVGObservable (nsISVGValue* observable, // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { if (mIsDirty) { nsCOMPtr region = DoReflow(); @@ -588,10 +594,11 @@ nsSVGForeignObjectFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGForeignObjectFrame::NotifyCanvasTMChanged() +nsSVGForeignObjectFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { mCanvasTM = nsnull; - Update(); + if (!suppressInvalidation) + Update(); return NS_OK; } @@ -622,6 +629,14 @@ nsSVGForeignObjectFrame::SetMatrixPropagation(PRBool aPropagate) return NS_OK; } +NS_IMETHODIMP +nsSVGForeignObjectFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM) +{ + mOverrideCTM = aCTM; + return NS_OK; +} + + NS_IMETHODIMP nsSVGForeignObjectFrame::GetBBox(nsIDOMSVGRect **_retval) { @@ -685,7 +700,12 @@ nsSVGForeignObjectFrame::GetCanvasTM() { if (!mPropagateTransform) { nsIDOMSVGMatrix *retval; - NS_NewSVGMatrix(&retval); + if (mOverrideCTM) { + retval = mOverrideCTM; + NS_ADDREF(retval); + } else { + NS_NewSVGMatrix(&retval); + } return retval; } diff --git a/mozilla/layout/svg/base/src/nsSVGGFrame.cpp b/mozilla/layout/svg/base/src/nsSVGGFrame.cpp index 6682107b994..d8385601ff1 100644 --- a/mozilla/layout/svg/base/src/nsSVGGFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGGFrame.cpp @@ -48,6 +48,8 @@ #include "nsISVGRendererCanvas.h" #include "nsLayoutAtoms.h" #include "nsSVGUtils.h" +#include "nsSVGFilterFrame.h" +#include "nsISVGValueUtils.h" #include //---------------------------------------------------------------------- @@ -81,11 +83,20 @@ 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) +nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { nsCOMPtr surface; @@ -94,6 +105,26 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips 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; + } + } + nsSVGClipPathFrame *clip = NULL; aURI = GetStyleSVGReset()->mClipPath; if (aURI) { @@ -135,7 +166,7 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->PaintSVG(canvas, dirtyRectTwips); + SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); } if (surface) { @@ -212,14 +243,80 @@ nsSVGGFrame::SetMatrixPropagation(PRBool aPropagate) return NS_OK; } +NS_IMETHODIMP +nsSVGGFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM) +{ + mOverrideCTM = aCTM; + return NS_OK; +} + already_AddRefed nsSVGGFrame::GetCanvasTM() { if (!mPropagateTransform) { nsIDOMSVGMatrix *retval; - NS_NewSVGMatrix(&retval); + if (mOverrideCTM) { + retval = mOverrideCTM; + NS_ADDREF(retval); + } else { + NS_NewSVGMatrix(&retval); + } return retval; } return nsSVGDefsFrame::GetCanvasTM(); } + +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 = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + + return NS_OK; + } + + return nsSVGGFrameBase::WillModifySVGObservable(observable, aModType); +} + +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 = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + if (mFilter) + mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion)); + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + + if (region) + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + } + + return nsSVGGFrameBase::DidModifySVGObservable(observable, aModType); +} diff --git a/mozilla/layout/svg/base/src/nsSVGGFrame.h b/mozilla/layout/svg/base/src/nsSVGGFrame.h index d408ab3cdce..059bba2509e 100644 --- a/mozilla/layout/svg/base/src/nsSVGGFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGGFrame.h @@ -43,10 +43,14 @@ typedef nsSVGDefsFrame nsSVGGFrameBase; +class nsISVGFilterFrame; + class nsSVGGFrame : public nsSVGGFrameBase { public: - nsSVGGFrame() : mPropagateTransform(PR_TRUE) {} + nsSVGGFrame() : mFilter(nsnull), mPropagateTransform(PR_TRUE) {} + virtual ~nsSVGGFrame(); + /** * Get the "type" of the frame @@ -67,15 +71,34 @@ protected: NS_NewSVGGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame); // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) 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 GetCanvasTM(); + // nsISVGValueObserver + NS_IMETHOD WillModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + nsISVGValue::modificationType aModType); + + nsCOMPtr mOverrideCTM; + + nsCOMPtr mFilterRegion; + nsISVGFilterFrame *mFilter; + PRBool mPropagateTransform; }; diff --git a/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.cpp b/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.cpp index 89fd6fdce22..fa524efba06 100644 --- a/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.cpp @@ -197,7 +197,9 @@ nsSVGGenericContainerFrame::GetType() const // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { #ifdef DEBUG // printf("nsSVGGenericContainer(%p)::Paint\n", this); @@ -207,7 +209,7 @@ nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->PaintSVG(canvas, dirtyRectTwips); + SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); } return NS_OK; @@ -282,14 +284,14 @@ nsSVGGenericContainerFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGGenericContainerFrame::NotifyCanvasTMChanged() +nsSVGGenericContainerFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) { nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(suppressInvalidation); } } return NS_OK; diff --git a/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.h b/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.h index 179411ba4c8..31758bad250 100644 --- a/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGGenericContainerFrame.h @@ -104,15 +104,22 @@ public: #endif // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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: nsISVGOuterSVGFrame*GetOuterSVGFrame(); diff --git a/mozilla/layout/svg/base/src/nsSVGGlyphFrame.cpp b/mozilla/layout/svg/base/src/nsSVGGlyphFrame.cpp index ab464b9d13d..6b4ef221cd8 100644 --- a/mozilla/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -131,15 +131,22 @@ public: nsISVGValue::modificationType aModType); // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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 @@ -177,7 +184,8 @@ public: NS_IMETHOD_(void) NotifyGlyphFragmentTreeUnsuspended(); protected: - void UpdateGeometry(PRUint32 flags, PRBool bRedraw=PR_TRUE); + void UpdateGeometry(PRUint32 flags, PRBool bRedraw, + PRBool suppressInvalidation); void UpdateMetrics(PRUint32 flags); void UpdateFragmentTree(); nsISVGOuterSVGFrame *GetOuterSVGFrame(); @@ -321,7 +329,7 @@ nsSVGGlyphFrame::Update(PRUint32 aFlags) outerSVGFrame->SuspendRedraw(); UpdateFragmentTree(); UpdateMetrics(aFlags); - UpdateGeometry(aFlags); + UpdateGeometry(aFlags, PR_TRUE, PR_FALSE); outerSVGFrame->UnsuspendRedraw(); return NS_OK; @@ -369,7 +377,7 @@ nsSVGGlyphFrame::SetSelected(nsPresContext* aPresContext, UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_HIGHLIGHT | nsISVGGlyphGeometrySource::UPDATEMASK_HAS_HIGHLIGHT, - PR_FALSE); + PR_FALSE, PR_FALSE); return NS_OK; } @@ -444,7 +452,9 @@ nsSVGGlyphFrame::DidModifySVGObservable (nsISVGValue* observable, // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { #ifdef DEBUG //printf("nsSVGGlyphFrame(%p)::Paint\n", this); @@ -523,9 +533,10 @@ nsSVGGlyphFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGGlyphFrame::NotifyCanvasTMChanged() +nsSVGGlyphFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { - UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_CANVAS_TM); + UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_CANVAS_TM, + PR_TRUE, suppressInvalidation); return NS_OK; } @@ -1129,7 +1140,7 @@ nsSVGGlyphFrame::SetGlyphPosition(float x, float y) mX = x; mY = y; UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_X | - nsISVGGlyphGeometrySource::UPDATEMASK_Y); + nsISVGGlyphGeometrySource::UPDATEMASK_Y, PR_TRUE, PR_FALSE); } NS_IMETHODIMP_(float) @@ -1363,7 +1374,8 @@ nsSVGGlyphFrame::NotifyGlyphFragmentTreeUnsuspended() //---------------------------------------------------------------------- // -void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw) +void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw, + PRBool suppressInvalidation) { mGeometryUpdateFlags |= flags; @@ -1373,6 +1385,11 @@ void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw) return; } + if (suppressInvalidation) { + mGeometryUpdateFlags = 0; + return; + } + PRBool suspended; outerSVGFrame->IsRedrawSuspended(&suspended); if (!suspended) { @@ -1381,21 +1398,21 @@ void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw) nsCOMPtr dirty_region; if (mGeometry) mGeometry->Update(mGeometryUpdateFlags, getter_AddRefs(dirty_region)); - if (dirty_region) { - // if we're being used as a clippath, this will get called - // during the paint - don't need to invalidate (which causes - // us to loop busy-painting) - nsIView *view = GetClosestView(); - if (!view) return; - nsIViewManager *vm = view->GetViewManager(); - PRBool painting; - vm->IsPainting(painting); + mGeometryUpdateFlags = 0; - if (!painting) + if (suppressInvalidation) + return; + + nsCOMPtr filter_region; + nsSVGUtils::FindFilterInvalidation(this, + getter_AddRefs(filter_region)); + if (filter_region) { + outerSVGFrame->InvalidateRegion(filter_region, bRedraw); + } else { + if (dirty_region) outerSVGFrame->InvalidateRegion(dirty_region, bRedraw); } - mGeometryUpdateFlags = 0; } } diff --git a/mozilla/layout/svg/base/src/nsSVGGradientFrame.cpp b/mozilla/layout/svg/base/src/nsSVGGradientFrame.cpp index a8fc74bb3cf..97d4016cdba 100644 --- a/mozilla/layout/svg/base/src/nsSVGGradientFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGGradientFrame.cpp @@ -479,10 +479,10 @@ nsSVGGradientFrame::GetGradientTransform(nsIDOMSVGMatrix **aGradientTransform, nsCOMPtr rect; if (frame) { frame->SetMatrixPropagation(PR_FALSE); - frame->NotifyCanvasTMChanged(); + frame->NotifyCanvasTMChanged(PR_TRUE); frame->GetBBox(getter_AddRefs(rect)); frame->SetMatrixPropagation(PR_TRUE); - frame->NotifyCanvasTMChanged(); + frame->NotifyCanvasTMChanged(PR_TRUE); } if (rect) { float x, y, width, height; diff --git a/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp b/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp index bb4b3bee7d6..f6e21d81368 100644 --- a/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp @@ -55,6 +55,8 @@ #include "imgIRequest.h" #include "nsSVGClipPathFrame.h" #include "nsLayoutAtoms.h" +#include "nsISVGValueUtils.h" +#include "nsSVGFilterFrame.h" #define NS_GET_BIT(rowptr, x) (rowptr[(x)>>3] & (1<<(7-(x)&0x7))) @@ -95,7 +97,9 @@ public: NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder); // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); // nsISVGGeometrySource interface: NS_IMETHOD GetStrokePaintType(PRUint16 *aStrokePaintType); @@ -305,11 +309,33 @@ NS_IMETHODIMP nsSVGImageFrame::ConstructPath(nsISVGRendererPathBuilder* pathBuil //---------------------------------------------------------------------- // nsISVGChildFrame methods: NS_IMETHODIMP -nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { 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 currentRequest; nsCOMPtr imageLoader = do_QueryInterface(mContent); @@ -336,7 +362,6 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectT canvas->PushClip(); /* check for a clip path */ - nsIURI *aURI; nsSVGClipPathFrame *clip = NULL; aURI = GetStyleSVGReset()->mClipPath; if (aURI) { diff --git a/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp b/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp index c7012bb2fe6..90757b85096 100644 --- a/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp @@ -54,6 +54,9 @@ #include "nsWeakReference.h" #include "nsSVGMatrix.h" #include "nsLayoutAtoms.h" +#include "nsSVGFilterFrame.h" +#include "nsISVGValueUtils.h" +#include "nsSVGUtils.h" typedef nsContainerFrame nsSVGInnerSVGFrameBase; @@ -114,15 +117,23 @@ public: #endif // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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: nsISVGOuterSVGFrame*GetOuterSVGFrame(); @@ -149,6 +160,11 @@ protected: nsCOMPtr mX; nsCOMPtr mY; + nsCOMPtr mOverrideCTM; + + nsCOMPtr mFilterRegion; + nsISVGFilterFrame *mFilter; + PRBool mPropagateTransform; }; @@ -167,7 +183,8 @@ NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* return NS_OK; } -nsSVGInnerSVGFrame::nsSVGInnerSVGFrame() : mPropagateTransform(PR_TRUE) +nsSVGInnerSVGFrame::nsSVGInnerSVGFrame() : mFilter(nsnull), + mPropagateTransform(PR_TRUE) { #ifdef DEBUG // printf("nsSVGInnerSVGFrame CTOR\n"); @@ -179,6 +196,9 @@ nsSVGInnerSVGFrame::~nsSVGInnerSVGFrame() #ifdef DEBUG // printf("~nsSVGInnerSVGFrame\n"); #endif + if (mFilter) { + NS_REMOVE_SVGVALUE_OBSERVER(mFilter); + } } nsresult nsSVGInnerSVGFrame::Init() @@ -351,12 +371,35 @@ nsSVGInnerSVGFrame::GetType() const // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { #ifdef DEBUG // printf("nsSVGInnerSVG(%p)::Paint\n", this); #endif + 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()) { @@ -393,7 +436,7 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRe nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->PaintSVG(canvas, dirtyRectTwips); + SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); } canvas->PopClip(); @@ -470,7 +513,7 @@ nsSVGInnerSVGFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGInnerSVGFrame::NotifyCanvasTMChanged() +nsSVGInnerSVGFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; @@ -480,7 +523,7 @@ nsSVGInnerSVGFrame::NotifyCanvasTMChanged() nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(suppressInvalidation); } } return NS_OK; @@ -521,6 +564,14 @@ nsSVGInnerSVGFrame::SetMatrixPropagation(PRBool aPropagate) return NS_OK; } +NS_IMETHODIMP +nsSVGInnerSVGFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM) +{ + mOverrideCTM = aCTM; + return NS_OK; +} + + NS_IMETHODIMP nsSVGInnerSVGFrame::GetBBox(nsIDOMSVGRect **_retval) { @@ -609,7 +660,7 @@ nsSVGInnerSVGFrame::NotifyViewportChange() nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(PR_FALSE); kid = kid->GetNextSibling(); } UnsuspendRedraw(); @@ -637,15 +688,20 @@ nsSVGInnerSVGFrame::GetOuterSVGFrame() already_AddRefed nsSVGInnerSVGFrame::GetCanvasTM() { + if (!mPropagateTransform) { + nsIDOMSVGMatrix *retval; + if (mOverrideCTM) { + retval = mOverrideCTM; + NS_ADDREF(retval); + } else { + NS_NewSVGMatrix(&retval); + } + return retval; + } + // parentTM * Translate(x,y) * viewboxToViewportTM if (!mCanvasTM) { - if (!mPropagateTransform) { - nsIDOMSVGMatrix *retval; - NS_NewSVGMatrix(&retval); - return retval; - } - // get the transform from our parent's coordinate system to ours: NS_ASSERTION(mParent, "null parent"); nsISVGContainerFrame *containerFrame; @@ -698,14 +754,50 @@ NS_IMETHODIMP nsSVGInnerSVGFrame::WillModifySVGObservable(nsISVGValue* observable, nsISVGValue::modificationType aModType) { - return NS_OK; + 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 = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + } } NS_IMETHODIMP nsSVGInnerSVGFrame::DidModifySVGObservable (nsISVGValue* observable, nsISVGValue::modificationType aModType) { - NotifyViewportChange(); - + nsISVGFilterFrame *filter; + CallQueryInterface(observable, &filter); + + if (filter) { + if (aModType == nsISVGValue::mod_die) { + mFilter = nsnull; + mFilterRegion = nsnull; + } + + nsISVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + if (mFilter) + mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion)); + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + + if (region) + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + } else { + NotifyViewportChange(); + } + return NS_OK; } diff --git a/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp b/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp index 779482cfb32..b25148ca996 100644 --- a/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp @@ -355,8 +355,8 @@ nsSVGMarkerFrame::PaintMark(nsISVGRendererCanvas *aCanvas, nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); - SVGFrame->PaintSVG(aCanvas, dirtyRectTwips); + SVGFrame->NotifyCanvasTMChanged(PR_TRUE); + SVGFrame->PaintSVG(aCanvas, dirtyRectTwips, PR_FALSE); } } @@ -385,7 +385,7 @@ NS_IMETHODIMP_(already_AddRefed) nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(PR_TRUE); nsCOMPtr dirty_region = SVGFrame->GetCoveredRegion(); if (dirty_region) { diff --git a/mozilla/layout/svg/base/src/nsSVGOuterSVGFrame.cpp b/mozilla/layout/svg/base/src/nsSVGOuterSVGFrame.cpp index 1b835a0a61d..2c5e403d89b 100644 --- a/mozilla/layout/svg/base/src/nsSVGOuterSVGFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGOuterSVGFrame.cpp @@ -845,7 +845,7 @@ nsSVGOuterSVGFrame::Paint(nsPresContext* aPresContext, nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->PaintSVG(canvas, aDirtyRect); + SVGFrame->PaintSVG(canvas, aDirtyRect, PR_FALSE); } canvas->Flush(); @@ -1020,7 +1020,7 @@ nsSVGOuterSVGFrame::NotifyViewportChange() nsISVGChildFrame* SVGFrame=nsnull; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(PR_FALSE); kid = kid->GetNextSibling(); } UnsuspendRedraw(); diff --git a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index a6314efa04a..62f985eabb6 100644 --- a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -61,13 +61,14 @@ #include "nsISVGRendererCanvas.h" #include "nsIViewManager.h" #include "nsSVGUtils.h" +#include "nsSVGFilterFrame.h" //////////////////////////////////////////////////////////////////////// // nsSVGPathGeometryFrame nsSVGPathGeometryFrame::nsSVGPathGeometryFrame() : mUpdateFlags(0), mPropagateTransform(PR_TRUE), - mFillGradient(nsnull), mStrokeGradient(nsnull) + mFillGradient(nsnull), mStrokeGradient(nsnull), mFilter(nsnull) { #ifdef DEBUG // printf("nsSVGPathGeometryFrame %p CTOR\n", this); @@ -91,6 +92,9 @@ nsSVGPathGeometryFrame::~nsSVGPathGeometryFrame() if (mStrokeGradient) { NS_REMOVE_SVGVALUE_OBSERVER(mStrokeGradient); } + if (mFilter) { + NS_REMOVE_SVGVALUE_OBSERVER(mFilter); + } } //---------------------------------------------------------------------- @@ -163,6 +167,10 @@ nsSVGPathGeometryFrame::DidSetStyleContext(nsPresContext* aPresContext) NS_REMOVE_SVGVALUE_OBSERVER(mStrokeGradient); mStrokeGradient = nsnull; } + if (mFilter) { + NS_REMOVE_SVGVALUE_OBSERVER(mFilter); + mFilter = nsnull; + } // XXX: we'd like to use the style_hint mechanism and the // ContentStateChanged/AttributeChanged functions for style changes @@ -208,15 +216,37 @@ nsSVGPathGeometryFrame::GetMarkerFrames(nsSVGMarkerFrame **markerStart, } NS_IMETHODIMP -nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { 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; + } + } + /* check for a clip path */ - nsIURI *aURI; - nsSVGClipPathFrame *clip = NULL; + nsSVGClipPathFrame *clip = nsnull; aURI = GetStyleSVGReset()->mClipPath; if (aURI) { NS_GetSVGClipPathFrame(&clip, aURI, mContent); @@ -371,9 +401,10 @@ nsSVGPathGeometryFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGPathGeometryFrame::NotifyCanvasTMChanged() +nsSVGPathGeometryFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { - UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_CANVAS_TM); + UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_CANVAS_TM, + suppressInvalidation); return NS_OK; } @@ -409,6 +440,13 @@ nsSVGPathGeometryFrame::SetMatrixPropagation(PRBool aPropagate) return NS_OK; } +NS_IMETHODIMP +nsSVGPathGeometryFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM) +{ + mOverrideCTM = aCTM; + return NS_OK; +} + NS_IMETHODIMP nsSVGPathGeometryFrame::GetBBox(nsIDOMSVGRect **_retval) { @@ -424,6 +462,21 @@ 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 = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + } + return NS_OK; } @@ -433,11 +486,15 @@ nsSVGPathGeometryFrame::DidModifySVGObservable (nsISVGValue* observable, nsISVGValue::modificationType aModType) { // Is this a gradient? - nsCOMPtrval = do_QueryInterface(observable); - if (val) { + nsCOMPtr gradient = do_QueryInterface(observable); + + nsISVGFilterFrame *filter; + CallQueryInterface(observable, &filter); + + if (gradient) { // Yes, we need to handle this differently nsCOMPtrfill = do_QueryInterface(mFillGradient); - if (fill == val) { + if (fill == gradient) { if (aModType == nsISVGValue::mod_die) { mFillGradient = nsnull; } @@ -449,6 +506,13 @@ 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 { // No, all of our other observables update the canvastm by default UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_CANVAS_TM); @@ -475,8 +539,14 @@ nsSVGPathGeometryFrame::GetCanvasTM(nsIDOMSVGMatrix * *aCTM) { *aCTM = nsnull; - if (!mPropagateTransform) + if (!mPropagateTransform) { + if (mOverrideCTM) { + *aCTM = mOverrideCTM; + NS_ADDREF(*aCTM); + return NS_OK; + } return NS_NewSVGMatrix(aCTM); + } nsISVGContainerFrame *containerFrame; mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame); @@ -822,7 +892,8 @@ nsSVGPathGeometryFrame::GetGeometry() return mGeometry; } -void nsSVGPathGeometryFrame::UpdateGraphic(PRUint32 flags) +void nsSVGPathGeometryFrame::UpdateGraphic(PRUint32 flags, + PRBool suppressInvalidation) { mUpdateFlags |= flags; @@ -838,21 +909,22 @@ void nsSVGPathGeometryFrame::UpdateGraphic(PRUint32 flags) nsCOMPtr dirty_region; if (GetGeometry()) GetGeometry()->Update(mUpdateFlags, getter_AddRefs(dirty_region)); - if (dirty_region) { - // if we're painting a marker, this will get called during paint - // when the region already be invalidated as needed - nsIView *view = GetClosestView(); - if (!view) return; - nsIViewManager *vm = view->GetViewManager(); - PRBool painting; - vm->IsPainting(painting); + mUpdateFlags = 0; - if (!painting) + if (suppressInvalidation) + return; + + nsCOMPtr filter_region; + nsSVGUtils::FindFilterInvalidation(this, + getter_AddRefs(filter_region)); + if (filter_region) { + outerSVGFrame->InvalidateRegion(filter_region, PR_TRUE); + } else { + if (dirty_region) outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE); } - mUpdateFlags = 0; - } + } } nsISVGOuterSVGFrame * diff --git a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h index d55a6c1ea1b..819d84a2dcc 100644 --- a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h @@ -54,6 +54,7 @@ class nsPresContext; class nsIDOMSVGMatrix; class nsISVGRendererRegion; class nsSVGMarkerFrame; +class nsISVGFilterFrame; typedef nsFrame nsSVGPathGeometryFrameBase; @@ -111,15 +112,23 @@ protected: nsISVGValue::modificationType aModType); // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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 @@ -135,16 +144,20 @@ protected: protected: NS_IMETHOD InitSVG(); - void UpdateGraphic(PRUint32 flags); + void UpdateGraphic(PRUint32 flags, PRBool suppressInvalidation = PR_FALSE); nsISVGOuterSVGFrame *GetOuterSVGFrame(); nsISVGRendererPathGeometry *GetGeometry(); + nsCOMPtr mFilterRegion; + nsISVGFilterFrame *mFilter; + private: nsCOMPtr mGeometry; PRUint32 mUpdateFlags; PRBool mPropagateTransform; nsCOMPtr mFillGradient; nsCOMPtr mStrokeGradient; + nsCOMPtr mOverrideCTM; void GetMarkerFrames(nsSVGMarkerFrame **markerStart, nsSVGMarkerFrame **markerMid, diff --git a/mozilla/layout/svg/base/src/nsSVGTSpanFrame.cpp b/mozilla/layout/svg/base/src/nsSVGTSpanFrame.cpp index c607e0290f2..d5720ad55a8 100644 --- a/mozilla/layout/svg/base/src/nsSVGTSpanFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGTSpanFrame.cpp @@ -278,7 +278,7 @@ nsSVGTSpanFrame::DidModifySVGObservable (nsISVGValue* observable, nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(); // XXX + SVGFrame->NotifyCanvasTMChanged(PR_FALSE); // XXX kid = kid->GetNextSibling(); } return NS_OK; @@ -289,7 +289,9 @@ nsSVGTSpanFrame::DidModifySVGObservable (nsISVGValue* observable, // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { #ifdef DEBUG // printf("nsSVGTSpanFrame(%p)::Paint\n", this); @@ -300,7 +302,7 @@ nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectT nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->PaintSVG(canvas, dirtyRectTwips); + SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); kid = kid->GetNextSibling(); } @@ -375,14 +377,14 @@ nsSVGTSpanFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGTSpanFrame::NotifyCanvasTMChanged() +nsSVGTSpanFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { nsIFrame* kid = mFrames.FirstChild(); while (kid) { nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(suppressInvalidation); } kid = kid->GetNextSibling(); } @@ -426,6 +428,13 @@ nsSVGTSpanFrame::SetMatrixPropagation(PRBool aPropagate) return NS_OK; } +NS_IMETHODIMP +nsSVGTSpanFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM) +{ + mOverrideCTM = aCTM; + return NS_OK; +} + NS_IMETHODIMP nsSVGTSpanFrame::GetBBox(nsIDOMSVGRect **_retval) { @@ -455,7 +464,12 @@ nsSVGTSpanFrame::GetCanvasTM() { if (!mPropagateTransform) { nsIDOMSVGMatrix *retval; - NS_NewSVGMatrix(&retval); + if (mOverrideCTM) { + retval = mOverrideCTM; + NS_ADDREF(retval); + } else { + NS_NewSVGMatrix(&retval); + } return retval; } diff --git a/mozilla/layout/svg/base/src/nsSVGTSpanFrame.h b/mozilla/layout/svg/base/src/nsSVGTSpanFrame.h index 07597259ab0..e6404510348 100644 --- a/mozilla/layout/svg/base/src/nsSVGTSpanFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGTSpanFrame.h @@ -131,15 +131,22 @@ public: // implementation inherited from nsSupportsWeakReference // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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: nsISVGOuterSVGFrame *GetOuterSVGFrame(); @@ -171,6 +178,7 @@ protected: nsISVGGlyphFragmentNode *GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node); private: + nsCOMPtr mOverrideCTM; PRUint32 mCharOffset; // index of first character of this node relative to the enclosing -element PRBool mFragmentTreeDirty; PRBool mPropagateTransform; diff --git a/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp b/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp index 8fb930a3912..428dfdb0c97 100644 --- a/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp @@ -66,6 +66,8 @@ #include "nsLayoutAtoms.h" #include "nsISVGPathFlatten.h" #include "nsSVGUtils.h" +#include "nsSVGFilterFrame.h" +#include "nsSVGUtils.h" typedef nsContainerFrame nsSVGTextFrameBase; @@ -144,15 +146,23 @@ public: // implementation inherited from nsSupportsWeakReference // nsISVGChildFrame interface: - NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips); + NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter); NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit); NS_IMETHOD_(already_AddRefed) GetCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(); + NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); 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: nsISVGOuterSVGFrame *GetOuterSVGFrame(); @@ -195,7 +205,11 @@ protected: PRBool mPositioningDirty; nsCOMPtr mCanvasTM; + nsCOMPtr mOverrideCTM; PRBool mPropagateTransform; + + nsCOMPtr mFilterRegion; + nsISVGFilterFrame *mFilter; }; //---------------------------------------------------------------------- @@ -228,7 +242,7 @@ NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsSVGTextFrame::nsSVGTextFrame() : mFragmentTreeState(suspended), mMetricsState(suspended), mFragmentTreeDirty(PR_FALSE), mPositioningDirty(PR_FALSE), - mPropagateTransform(PR_TRUE) + mPropagateTransform(PR_TRUE), mFilter(nsnull) { } @@ -262,6 +276,10 @@ nsSVGTextFrame::~nsSVGTextFrame() transformable->GetTransform(getter_AddRefs(transforms)); NS_REMOVE_SVGVALUE_OBSERVER(transforms); } + + if (mFilter) { + NS_REMOVE_SVGVALUE_OBSERVER(mFilter); + } } nsresult nsSVGTextFrame::Init() @@ -453,6 +471,20 @@ NS_IMETHODIMP nsSVGTextFrame::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 = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + } return NS_OK; } @@ -461,8 +493,29 @@ NS_IMETHODIMP nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable, nsISVGValue::modificationType aModType) { + nsISVGFilterFrame *filter; + CallQueryInterface(observable, &filter); nsCOMPtr transforms = GetTransform(); - if (SameCOMIdentity(observable, transforms)) { + + if (filter) { + if (aModType == nsISVGValue::mod_die) { + mFilter = nsnull; + mFilterRegion = nsnull; + } + + nsISVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame(); + if (!outerSVGFrame) + return NS_ERROR_FAILURE; + + if (mFilter) + mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion)); + + nsCOMPtr region; + nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); + + if (region) + outerSVGFrame->InvalidateRegion(region, PR_TRUE); + } else if (SameCOMIdentity(observable, transforms)) { // transform has changed // make sure our cached transform matrix gets (lazily) updated @@ -473,7 +526,7 @@ nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable, nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(PR_FALSE); kid = kid->GetNextSibling(); } } @@ -522,18 +575,39 @@ nsSVGTextFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval) // nsISVGChildFrame methods NS_IMETHODIMP -nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) +nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas, + const nsRect& dirtyRectTwips, + PRBool ignoreFilter) { #ifdef DEBUG // printf("nsSVGTextFrame(%p)::Paint\n", this); #endif + /* check for filter */ + + if (!ignoreFilter) { + if (!mFilter) { + 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; + } + } + nsIFrame* kid = mFrames.FirstChild(); while (kid) { nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) - SVGFrame->PaintSVG(canvas, dirtyRectTwips); + SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); kid = kid->GetNextSibling(); } @@ -624,7 +698,7 @@ nsSVGTextFrame::InitialUpdate() } NS_IMETHODIMP -nsSVGTextFrame::NotifyCanvasTMChanged() +nsSVGTextFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; @@ -634,7 +708,7 @@ nsSVGTextFrame::NotifyCanvasTMChanged() nsISVGChildFrame* SVGFrame=0; kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->NotifyCanvasTMChanged(suppressInvalidation); } kid = kid->GetNextSibling(); } @@ -720,6 +794,13 @@ nsSVGTextFrame::SetMatrixPropagation(PRBool aPropagate) return NS_OK; } +NS_IMETHODIMP +nsSVGTextFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM) +{ + mOverrideCTM = aCTM; + return NS_OK; +} + NS_IMETHODIMP nsSVGTextFrame::GetBBox(nsIDOMSVGRect **_retval) { @@ -748,13 +829,18 @@ nsSVGTextFrame::GetOuterSVGFrame() already_AddRefed nsSVGTextFrame::GetCanvasTM() { - if (!mCanvasTM) { - if (!mPropagateTransform) { - nsIDOMSVGMatrix *retval; + if (!mPropagateTransform) { + nsIDOMSVGMatrix *retval; + if (mOverrideCTM) { + retval = mOverrideCTM; + NS_ADDREF(retval); + } else { NS_NewSVGMatrix(&retval); - return retval; } + return retval; + } + if (!mCanvasTM) { // get our parent's tm and append local transforms (if any): NS_ASSERTION(mParent, "null parent"); nsISVGContainerFrame *containerFrame; diff --git a/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp b/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp index fbd339093fc..586de861025 100644 --- a/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGUseFrame.cpp @@ -174,7 +174,12 @@ nsSVGUseFrame::GetCanvasTM() { if (!mPropagateTransform) { nsIDOMSVGMatrix *retval; - NS_NewSVGMatrix(&retval); + if (mOverrideCTM) { + retval = mOverrideCTM; + NS_ADDREF(retval); + } else { + NS_NewSVGMatrix(&retval); + } return retval; } diff --git a/mozilla/layout/svg/base/src/nsSVGUtils.cpp b/mozilla/layout/svg/base/src/nsSVGUtils.cpp index d2d0b0ade93..1988e438cc1 100644 --- a/mozilla/layout/svg/base/src/nsSVGUtils.cpp +++ b/mozilla/layout/svg/base/src/nsSVGUtils.cpp @@ -57,6 +57,11 @@ #include "nsContentDLF.h" #include "nsContentUtils.h" #include "nsISVGRenderer.h" +#include "nsSVGFilterFrame.h" +#include "nsINameSpaceManager.h" +#include "nsISVGChildFrame.h" +#include "nsIDOMSVGPoint.h" +#include "nsSVGPoint.h" static PRBool gSVGEnabled; static PRBool gSVGRendererAvailable = PR_FALSE; @@ -316,3 +321,112 @@ nsSVGUtils::GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval) return NS_ERROR_FAILURE; } + +void +nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame, + nsISVGRendererRegion **aRegion) +{ + nsCOMPtr region, tmp; + + while (aFrame != nsnull) { + nsISVGChildFrame *svg; + CallQueryInterface(aFrame, &svg); + if (svg) + svg->GetFilterRegion(getter_AddRefs(tmp)); + if (tmp) + region = tmp; + aFrame = aFrame->GetParent(); + } + + *aRegion = region; + NS_IF_ADDREF(*aRegion); +} + +float +nsSVGUtils::ObjectSpace(nsIDOMSVGRect *rect, + nsIDOMSVGLength *length, + ctxDirection direction) +{ + PRUint16 type; + float fraction, axis; + + length->GetUnitType(&type); + switch (direction) { + case X: + rect->GetWidth(&axis); + break; + case Y: + rect->GetHeight(&axis); + break; + case XY: + { + float width, height; + rect->GetWidth(&width); + rect->GetHeight(&height); + axis = sqrt(width * width + height * height)/sqrt(2.0f); + } + } + + if (type == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { + length->GetValueInSpecifiedUnits(&fraction); + fraction /= 100.0; + } else + length->GetValue(&fraction); + + return fraction * axis; +} + +float +nsSVGUtils::UserSpace(nsIContent *content, + nsIDOMSVGLength *length, + ctxDirection direction) +{ + PRUint16 units; + float value; + + length->GetUnitType(&units); + length->GetValueInSpecifiedUnits(&value); + + nsCOMPtr val; + NS_NewSVGLength(getter_AddRefs(val), value, units); + + nsCOMPtr element = do_QueryInterface(content); + nsCOMPtr svg; + element->GetOwnerSVGElement(getter_AddRefs(svg)); + nsCOMPtr ctx = do_QueryInterface(svg); + + if (ctx) { + switch (direction) { + case X: + val->SetContext(nsRefPtr(ctx->GetContextX())); + break; + case Y: + val->SetContext(nsRefPtr(ctx->GetContextY())); + break; + case XY: + val->SetContext(nsRefPtr(ctx->GetContextUnspecified())); + break; + } + } + + val->GetValue(&value); + return value; +} + +void +nsSVGUtils::TransformPoint(nsIDOMSVGMatrix *matrix, + float *x, float *y) +{ + nsCOMPtr point; + NS_NewSVGPoint(getter_AddRefs(point), *x, *y); + if (!point) + return; + + nsCOMPtr xfpoint; + point->MatrixTransform(matrix, getter_AddRefs(xfpoint)); + if (!xfpoint) + return; + + xfpoint->GetX(x); + xfpoint->GetY(y); +} diff --git a/mozilla/layout/svg/base/src/nsSVGUtils.h b/mozilla/layout/svg/base/src/nsSVGUtils.h index 649cc14f638..e40aae01d0e 100644 --- a/mozilla/layout/svg/base/src/nsSVGUtils.h +++ b/mozilla/layout/svg/base/src/nsSVGUtils.h @@ -44,6 +44,9 @@ class nsIDOMSVGRect; class nsFrameList; class nsIFrame; struct nsStyleSVGPaint; +class nsISVGRendererRegion; +class nsIDOMSVGLength; +class nsIDOMSVGMatrix; class nsSVGUtils { @@ -79,6 +82,39 @@ public: * Creates a bounding box by walking the children and doing union. */ static nsresult GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval); + + /* + * Figures out the worst case invalidation area for a frame, taking + * into account filters. Null return if no filter in the hierarcy. + */ + static void FindFilterInvalidation(nsIFrame *aFrame, + nsISVGRendererRegion **aRegion); + + /* enum for specifying coordinate direction for ObjectSpace/UserSpace */ + enum ctxDirection { X, Y, XY }; + + /* Computes the input length in terms of object space coordinates. + Input: rect - bounding box + length - length to be converted + direction - direction of length + */ + static float ObjectSpace(nsIDOMSVGRect *rect, + nsIDOMSVGLength *length, + ctxDirection direction); + + /* Computes the input length in terms of user space coordinates. + Input: content - object to be used for determining user space + length - length to be converted + direction - direction of length + */ + static float UserSpace(nsIContent *content, + nsIDOMSVGLength *length, + ctxDirection direction); + + /* Tranforms point by the matrix. In/out: x,y */ + static void + TransformPoint(nsIDOMSVGMatrix *matrix, + float *x, float *y); }; #endif