LCOV - code coverage report
Current view: directory - content/svg/content/src - nsSVGFilters.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1920 0 0.0 %
Date: 2012-06-02 Functions: 2066 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Mozilla SVG project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is IBM Corporation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      25                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "mozilla/Util.h"
      38                 : 
      39                 : #include "nsSVGElement.h"
      40                 : #include "nsGkAtoms.h"
      41                 : #include "nsSVGNumber2.h"
      42                 : #include "nsSVGNumberPair.h"
      43                 : #include "nsSVGInteger.h"
      44                 : #include "nsSVGIntegerPair.h"
      45                 : #include "nsSVGBoolean.h"
      46                 : #include "nsIDOMSVGFilters.h"
      47                 : #include "nsCOMPtr.h"
      48                 : #include "nsSVGFilterInstance.h"
      49                 : #include "nsIDOMSVGFilterElement.h"
      50                 : #include "nsSVGEnum.h"
      51                 : #include "SVGNumberList.h"
      52                 : #include "SVGAnimatedNumberList.h"
      53                 : #include "DOMSVGAnimatedNumberList.h"
      54                 : #include "nsSVGFilters.h"
      55                 : #include "nsLayoutUtils.h"
      56                 : #include "nsSVGUtils.h"
      57                 : #include "nsStyleContext.h"
      58                 : #include "nsIDocument.h"
      59                 : #include "nsIFrame.h"
      60                 : #include "gfxContext.h"
      61                 : #include "gfxMatrix.h"
      62                 : #include "imgIContainer.h"
      63                 : #include "nsNetUtil.h"
      64                 : #include "nsIInterfaceRequestorUtils.h"
      65                 : #include "nsSVGFilterElement.h"
      66                 : #include "nsSVGString.h"
      67                 : #include "nsSVGEffects.h"
      68                 : #include "gfxUtils.h"
      69                 : 
      70                 : #if defined(XP_WIN) 
      71                 : // Prevent Windows redefining LoadImage
      72                 : #undef LoadImage
      73                 : #endif
      74                 : 
      75                 : #define NUM_ENTRIES_IN_4x5_MATRIX 20
      76                 : 
      77                 : using namespace mozilla;
      78                 : using namespace mozilla::dom;
      79                 : 
      80                 : static void
      81               0 : CopyDataRect(PRUint8 *aDest, const PRUint8 *aSrc, PRUint32 aStride,
      82                 :              const nsIntRect& aDataRect)
      83                 : {
      84               0 :   for (PRInt32 y = aDataRect.y; y < aDataRect.YMost(); y++) {
      85               0 :     memcpy(aDest + y * aStride + 4 * aDataRect.x,
      86               0 :            aSrc + y * aStride + 4 * aDataRect.x,
      87               0 :            4 * aDataRect.width);
      88                 :   }
      89               0 : }
      90                 : 
      91                 : static void
      92               0 : CopyRect(const nsSVGFE::Image* aDest, const nsSVGFE::Image* aSrc, const nsIntRect& aDataRect)
      93                 : {
      94               0 :   NS_ASSERTION(aDest->mImage->Stride() == aSrc->mImage->Stride(), "stride mismatch");
      95               0 :   NS_ASSERTION(aDest->mImage->GetSize() == aSrc->mImage->GetSize(), "size mismatch");
      96               0 :   NS_ASSERTION(nsIntRect(0, 0, aDest->mImage->Width(), aDest->mImage->Height()).Contains(aDataRect),
      97                 :                "aDataRect out of bounds");
      98                 : 
      99               0 :   CopyDataRect(aDest->mImage->Data(), aSrc->mImage->Data(),
     100               0 :                aSrc->mImage->Stride(), aDataRect);
     101               0 : }
     102                 : 
     103                 : //--------------------Filter Element Base Class-----------------------
     104                 : 
     105                 : nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] =
     106                 : {
     107                 :   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, nsSVGUtils::X },
     108                 :   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, nsSVGUtils::Y },
     109                 :   { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, nsSVGUtils::X },
     110                 :   { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, nsSVGUtils::Y }
     111                 : };
     112                 : 
     113                 : //----------------------------------------------------------------------
     114                 : // nsISupports methods
     115                 : 
     116               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase)
     117               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase)
     118                 : 
     119                 : NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFE, NS_SVG_FE_CID)
     120                 : 
     121               0 : NS_INTERFACE_MAP_BEGIN(nsSVGFE)
     122                 :    // nsISupports is an ambiguous base of nsSVGFE so we have to work
     123                 :    // around that
     124               0 :    if ( aIID.Equals(NS_GET_IID(nsSVGFE)) )
     125               0 :      foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
     126                 :    else
     127               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase)
     128                 : 
     129                 : //----------------------------------------------------------------------
     130                 : // Implementation
     131                 : 
     132                 : nsSVGFE::ScaleInfo
     133               0 : nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance,
     134                 :                             const Image *aSource, const Image *aTarget,
     135                 :                             const nsIntRect& aDataRect,
     136                 :                             nsSVGNumberPair *aKernelUnitLength)
     137                 : {
     138               0 :   ScaleInfo result;
     139               0 :   result.mRescaling = aKernelUnitLength->IsExplicitlySet();
     140               0 :   if (!result.mRescaling) {
     141               0 :     result.mSource = aSource->mImage;
     142               0 :     result.mTarget = aTarget->mImage;
     143               0 :     result.mDataRect = aDataRect;
     144               0 :     return result;
     145                 :   }
     146                 : 
     147                 :   gfxFloat kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X,
     148                 :                                                    aKernelUnitLength,
     149               0 :                                                    nsSVGNumberPair::eFirst);
     150                 :   gfxFloat kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y,
     151                 :                                                    aKernelUnitLength,
     152               0 :                                                    nsSVGNumberPair::eSecond);
     153               0 :   if (kernelX <= 0 || kernelY <= 0)
     154               0 :     return result;
     155                 : 
     156               0 :   bool overflow = false;
     157                 :   gfxIntSize scaledSize =
     158               0 :     nsSVGUtils::ConvertToSurfaceSize(gfxSize(aTarget->mImage->Width() / kernelX,
     159               0 :                                              aTarget->mImage->Height() / kernelY),
     160               0 :                                      &overflow);
     161                 :   // If the requested size based on the kernel unit is too big, we
     162                 :   // need to bail because the effect is pixel size dependent.  Also
     163                 :   // need to check if we ended up with a negative size (arithmetic
     164                 :   // overflow) or zero size (large kernel unit)
     165               0 :   if (overflow || scaledSize.width <= 0 || scaledSize.height <= 0)
     166               0 :     return result;
     167                 : 
     168               0 :   gfxRect r(aDataRect.x, aDataRect.y, aDataRect.width, aDataRect.height);
     169               0 :   r.Scale(1 / kernelX, 1 / kernelY);
     170               0 :   r.RoundOut();
     171               0 :   if (!gfxUtils::GfxRectToIntRect(r, &result.mDataRect))
     172               0 :     return result;
     173                 :   
     174                 :   result.mSource = new gfxImageSurface(scaledSize,
     175               0 :                                        gfxASurface::ImageFormatARGB32);
     176                 :   result.mTarget = new gfxImageSurface(scaledSize,
     177               0 :                                        gfxASurface::ImageFormatARGB32);
     178               0 :   if (!result.mSource || result.mSource->CairoStatus() ||
     179               0 :       !result.mTarget || result.mTarget->CairoStatus()) {
     180               0 :     result.mSource = nsnull;
     181               0 :     result.mTarget = nsnull;
     182               0 :     return result;
     183                 :   }
     184               0 :   result.mRealTarget = aTarget->mImage;
     185                 : 
     186               0 :   gfxContext ctx(result.mSource);
     187               0 :   ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
     188               0 :   ctx.Scale(double(scaledSize.width) / aTarget->mImage->Width(),
     189               0 :             double(scaledSize.height) / aTarget->mImage->Height());
     190               0 :   ctx.SetSource(aSource->mImage);
     191               0 :   ctx.Paint();
     192                 : 
     193                 :   // mTarget was already cleared when it was created
     194                 : 
     195                 :   return result;
     196                 : }
     197                 : 
     198                 : void
     199               0 : nsSVGFE::FinishScalingFilter(ScaleInfo *aScaleInfo)
     200                 : {
     201               0 :   if (!aScaleInfo->mRescaling)
     202               0 :     return;
     203                 : 
     204               0 :   gfxIntSize scaledSize = aScaleInfo->mTarget->GetSize();
     205                 : 
     206               0 :   gfxContext ctx(aScaleInfo->mRealTarget);
     207               0 :   ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
     208               0 :   ctx.Scale(double(aScaleInfo->mRealTarget->Width()) / scaledSize.width,
     209               0 :             double(aScaleInfo->mRealTarget->Height()) / scaledSize.height);
     210               0 :   ctx.SetSource(aScaleInfo->mTarget);
     211               0 :   ctx.Paint();
     212                 : }
     213                 : 
     214                 : nsIntRect
     215               0 : nsSVGFE::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
     216                 :                            const nsSVGFilterInstance& aInstance)
     217                 : {
     218               0 :   nsIntRect r;
     219               0 :   for (PRUint32 i = 0; i < aSourceBBoxes.Length(); ++i) {
     220               0 :     r.UnionRect(r, aSourceBBoxes[i]);
     221                 :   }
     222                 :   return r;
     223                 : }
     224                 : 
     225                 : void
     226               0 : nsSVGFE::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
     227                 :                                    nsTArray<nsIntRect>& aSourceBBoxes,
     228                 :                                    const nsSVGFilterInstance& aInstance)
     229                 : {
     230               0 :   for (PRUint32 i = 0; i < aSourceBBoxes.Length(); ++i) {
     231               0 :     aSourceBBoxes[i] = aTargetBBox;
     232                 :   }
     233               0 : }
     234                 : 
     235                 : nsIntRect
     236               0 : nsSVGFE::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
     237                 :                            const nsSVGFilterInstance& aInstance)
     238                 : {
     239               0 :   nsIntRect r;
     240               0 :   for (PRUint32 i = 0; i < aSourceChangeBoxes.Length(); ++i) {
     241               0 :     r.UnionRect(r, aSourceChangeBoxes[i]);
     242                 :   }
     243                 :   return r;
     244                 : }
     245                 : 
     246                 : void
     247               0 : nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
     248                 : {
     249               0 : }
     250                 : 
     251                 : bool
     252               0 : nsSVGFE::AttributeAffectsRendering(PRInt32 aNameSpaceID,
     253                 :                                    nsIAtom* aAttribute) const
     254                 : {
     255                 :   return aNameSpaceID == kNameSpaceID_None &&
     256                 :          (aAttribute == nsGkAtoms::x ||
     257                 :           aAttribute == nsGkAtoms::y ||
     258                 :           aAttribute == nsGkAtoms::width ||
     259                 :           aAttribute == nsGkAtoms::height ||
     260               0 :           aAttribute == nsGkAtoms::result);
     261                 : }
     262                 : 
     263                 : //----------------------------------------------------------------------
     264                 : // nsIDOMSVGFilterPrimitiveStandardAttributes methods
     265                 : 
     266                 : /* readonly attribute nsIDOMSVGAnimatedLength x; */
     267               0 : NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX)
     268                 : {
     269               0 :   return mLengthAttributes[X].ToDOMAnimatedLength(aX, this);
     270                 : }
     271                 : 
     272                 : /* readonly attribute nsIDOMSVGAnimatedLength y; */
     273               0 : NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY)
     274                 : {
     275               0 :   return mLengthAttributes[Y].ToDOMAnimatedLength(aY, this);
     276                 : }
     277                 : 
     278                 : /* readonly attribute nsIDOMSVGAnimatedLength width; */
     279               0 : NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth)
     280                 : {
     281               0 :   return mLengthAttributes[WIDTH].ToDOMAnimatedLength(aWidth, this);
     282                 : }
     283                 : 
     284                 : /* readonly attribute nsIDOMSVGAnimatedLength height; */
     285               0 : NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
     286                 : {
     287               0 :   return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
     288                 : }
     289                 : 
     290                 : /* readonly attribute nsIDOMSVGAnimatedString result; */
     291               0 : NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult)
     292                 : {
     293               0 :   return GetResultImageName().ToDOMAnimatedString(aResult, this);
     294                 : }
     295                 : 
     296                 : //----------------------------------------------------------------------
     297                 : // nsIContent methods
     298                 : 
     299                 : NS_IMETHODIMP_(bool)
     300               0 : nsSVGFE::IsAttributeMapped(const nsIAtom* name) const
     301                 : {
     302                 :   static const MappedAttributeEntry* const map[] = {
     303                 :     sFiltersMap
     304                 :   };
     305                 :   
     306               0 :   return FindAttributeDependence(name, map) ||
     307               0 :     nsSVGFEBase::IsAttributeMapped(name);
     308                 : }
     309                 : 
     310                 : //----------------------------------------------------------------------
     311                 : // nsSVGElement methods
     312                 : 
     313                 : /* virtual */ bool
     314               0 : nsSVGFE::HasValidDimensions() const
     315                 : {
     316               0 :   return (!mLengthAttributes[WIDTH].IsExplicitlySet() ||
     317               0 :            mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
     318               0 :          (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
     319               0 :            mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0);
     320                 : }
     321                 : 
     322                 : nsSVGElement::LengthAttributesInfo
     323               0 : nsSVGFE::GetLengthInfo()
     324                 : {
     325                 :   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
     326               0 :                               ArrayLength(sLengthInfo));
     327                 : }
     328                 : 
     329                 : //---------------------Gaussian Blur------------------------
     330                 : 
     331                 : typedef nsSVGFE nsSVGFEGaussianBlurElementBase;
     332                 : 
     333                 : class nsSVGFEGaussianBlurElement : public nsSVGFEGaussianBlurElementBase,
     334                 :                                    public nsIDOMSVGFEGaussianBlurElement
     335               0 : {
     336                 :   friend nsresult NS_NewSVGFEGaussianBlurElement(nsIContent **aResult,
     337                 :                                                  already_AddRefed<nsINodeInfo> aNodeInfo);
     338                 : protected:
     339               0 :   nsSVGFEGaussianBlurElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     340               0 :     : nsSVGFEGaussianBlurElementBase(aNodeInfo) {}
     341                 : 
     342                 : public:
     343                 :   // interfaces:
     344                 :   NS_DECL_ISUPPORTS_INHERITED
     345                 : 
     346                 :   // FE Base
     347               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEGaussianBlurElementBase::)
     348                 : 
     349                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
     350                 :                           const nsTArray<const Image*>& aSources,
     351                 :                           const Image* aTarget,
     352                 :                           const nsIntRect& aDataRect);
     353                 :   virtual bool AttributeAffectsRendering(
     354                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
     355               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
     356                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo >& aSources);
     357                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
     358                 :           const nsSVGFilterInstance& aInstance);
     359                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
     360                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
     361                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
     362                 :           const nsSVGFilterInstance& aInstance);
     363                 : 
     364                 :   // Gaussian
     365                 :   NS_DECL_NSIDOMSVGFEGAUSSIANBLURELEMENT
     366                 : 
     367               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEGaussianBlurElementBase::)
     368                 : 
     369               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEGaussianBlurElementBase::)
     370               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEGaussianBlurElementBase::)
     371                 : 
     372                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
     373                 : 
     374                 :   virtual nsXPCClassInfo* GetClassInfo();
     375                 : protected:
     376                 :   virtual NumberPairAttributesInfo GetNumberPairInfo();
     377                 :   virtual StringAttributesInfo GetStringInfo();
     378                 : 
     379                 :   enum { STD_DEV };
     380                 :   nsSVGNumberPair mNumberPairAttributes[1];
     381                 :   static NumberPairInfo sNumberPairInfo[1];
     382                 : 
     383                 :   enum { RESULT, IN1 };
     384                 :   nsSVGString mStringAttributes[2];
     385                 :   static StringInfo sStringInfo[2];
     386                 : 
     387                 : private:
     388                 :   nsresult GetDXY(PRUint32 *aDX, PRUint32 *aDY, const nsSVGFilterInstance& aInstance);
     389                 :   nsIntRect InflateRectForBlur(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
     390                 : 
     391                 :   void GaussianBlur(const Image *aSource, const Image *aTarget,
     392                 :                     const nsIntRect& aDataRect,
     393                 :                     PRUint32 aDX, PRUint32 aDY);
     394                 : };
     395                 : 
     396                 : nsSVGElement::NumberPairInfo nsSVGFEGaussianBlurElement::sNumberPairInfo[1] =
     397                 : {
     398                 :   { &nsGkAtoms::stdDeviation, 0, 0 }
     399                 : };
     400                 : 
     401                 : nsSVGElement::StringInfo nsSVGFEGaussianBlurElement::sStringInfo[2] =
     402                 : {
     403                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
     404                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
     405                 : };
     406                 : 
     407               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEGaussianBlur)
     408                 : 
     409                 : //----------------------------------------------------------------------
     410                 : // nsISupports methods
     411                 : 
     412               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEGaussianBlurElement,nsSVGFEGaussianBlurElementBase)
     413               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEGaussianBlurElement,nsSVGFEGaussianBlurElementBase)
     414                 : 
     415               0 : DOMCI_NODE_DATA(SVGFEGaussianBlurElement, nsSVGFEGaussianBlurElement)
     416                 : 
     417               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEGaussianBlurElement)
     418               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEGaussianBlurElement, nsIDOMNode,
     419                 :                            nsIDOMElement, nsIDOMSVGElement,
     420                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
     421                 :                            nsIDOMSVGFEGaussianBlurElement)
     422               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEGaussianBlurElement)
     423               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEGaussianBlurElementBase)
     424                 : 
     425                 : //----------------------------------------------------------------------
     426                 : // nsIDOMNode methods
     427                 : 
     428                 : 
     429               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEGaussianBlurElement)
     430                 : 
     431                 : 
     432                 : //----------------------------------------------------------------------
     433                 : // nsIDOMSVGFEGaussianBlurElement methods
     434                 : 
     435                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
     436               0 : NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
     437                 : {
     438               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
     439                 : }
     440                 : 
     441                 : /* readonly attribute nsIDOMSVGAnimatedNumber stdDeviationX; */
     442               0 : NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetStdDeviationX(nsIDOMSVGAnimatedNumber * *aX)
     443                 : {
     444               0 :   return mNumberPairAttributes[STD_DEV].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
     445                 : }
     446                 : 
     447                 : /* readonly attribute nsIDOMSVGAnimatedNumber stdDeviationY; */
     448               0 : NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetStdDeviationY(nsIDOMSVGAnimatedNumber * *aY)
     449                 : {
     450               0 :   return mNumberPairAttributes[STD_DEV].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
     451                 : }
     452                 : 
     453                 : NS_IMETHODIMP
     454               0 : nsSVGFEGaussianBlurElement::SetStdDeviation(float stdDeviationX, float stdDeviationY)
     455                 : {
     456               0 :   NS_ENSURE_FINITE2(stdDeviationX, stdDeviationY, NS_ERROR_ILLEGAL_VALUE);
     457               0 :   mNumberPairAttributes[STD_DEV].SetBaseValues(stdDeviationX, stdDeviationY, this);
     458               0 :   return NS_OK;
     459                 : }
     460                 : 
     461                 : /**
     462                 :  * We want to speed up 1/N integer divisions --- integer division is
     463                 :  * often rather slow.
     464                 :  * We know that our input numerators V are constrained to be <= 255*N,
     465                 :  * so the result of dividing by N always fits in 8 bits.
     466                 :  * So we can try approximating the division V/N as V*K/(2^24) (integer
     467                 :  * division, 32-bit multiply). Dividing by 2^24 is a simple shift so it's
     468                 :  * fast. The main problem is choosing a value for K; this function returns
     469                 :  * K's value.
     470                 :  * 
     471                 :  * If the result is correct for the extrema, V=0 and V=255*N, then we'll
     472                 :  * be in good shape since both the original function and our approximation
     473                 :  * are linear. V=0 always gives 0 in both cases, no problem there.
     474                 :  * For V=255*N, let's choose the largest K that doesn't cause overflow
     475                 :  * and ensure that it gives the right answer. The constraints are
     476                 :  *     (1)   255*N*K < 2^32
     477                 :  * and (2)   255*N*K >= 255*(2^24)
     478                 :  * 
     479                 :  * From (1) we find the best value of K is floor((2^32 - 1)/(255*N)).
     480                 :  * (2) tells us when this will be valid:
     481                 :  *    N*floor((2^32 - 1)/(255*N)) >= 2^24
     482                 :  * Now, floor(X) > X - 1, so (2) holds if
     483                 :  *    N*((2^32 - 1)/(255*N) - 1) >= 2^24
     484                 :  *         (2^32 - 1)/255 - 2^24 >= N
     485                 :  *                             N <= 65793
     486                 :  * 
     487                 :  * If all that math confuses you, this should convince you:
     488                 :  * > perl -e 'for($N=1;(255*$N*int(0xFFFFFFFF/(255*$N)))>>24==255;++$N){}print"$N\n"'
     489                 :  * 66052
     490                 :  * 
     491                 :  * So this is fine for all reasonable values of N. For larger values of N
     492                 :  * we may as well just use the same approximation and accept the fact that
     493                 :  * the output channel values will be a little low.
     494                 :  */
     495               0 : static PRUint32 ComputeScaledDivisor(PRUint32 aDivisor)
     496                 : {
     497               0 :   return PR_UINT32_MAX/(255*aDivisor);
     498                 : }
     499                 :   
     500                 : static void
     501               0 : BoxBlur(const PRUint8 *aInput, PRUint8 *aOutput,
     502                 :         PRInt32 aStrideMinor, PRInt32 aStartMinor, PRInt32 aEndMinor,
     503                 :         PRInt32 aLeftLobe, PRInt32 aRightLobe, bool aAlphaOnly)
     504                 : {
     505               0 :   PRInt32 boxSize = aLeftLobe + aRightLobe + 1;
     506               0 :   PRInt32 scaledDivisor = ComputeScaledDivisor(boxSize);
     507               0 :   PRInt32 sums[4] = {0, 0, 0, 0};
     508                 : 
     509               0 :   for (PRInt32 i=0; i < boxSize; i++) {
     510               0 :     PRInt32 pos = aStartMinor - aLeftLobe + i;
     511               0 :     pos = NS_MAX(pos, aStartMinor);
     512               0 :     pos = NS_MIN(pos, aEndMinor - 1);
     513                 : #define SUM(j)     sums[j] += aInput[aStrideMinor*pos + j];
     514               0 :     SUM(0); SUM(1); SUM(2); SUM(3);
     515                 : #undef SUM
     516                 :   }
     517                 : 
     518               0 :   aOutput += aStrideMinor*aStartMinor;
     519               0 :   if (aStartMinor + PRInt32(boxSize) <= aEndMinor) {
     520               0 :     const PRUint8 *lastInput = aInput + aStartMinor*aStrideMinor;
     521               0 :     const PRUint8 *nextInput = aInput + (aStartMinor + aRightLobe + 1)*aStrideMinor;
     522                 : #define OUTPUT(j)     aOutput[j] = (sums[j]*scaledDivisor) >> 24;
     523                 : #define SUM(j)        sums[j] += nextInput[j] - lastInput[j];
     524                 :     // process pixels in B, G, R, A order because that's 0, 1, 2, 3 for x86
     525                 : #define OUTPUT_PIXEL() \
     526                 :         if (!aAlphaOnly) { OUTPUT(GFX_ARGB32_OFFSET_B); \
     527                 :                            OUTPUT(GFX_ARGB32_OFFSET_G); \
     528                 :                            OUTPUT(GFX_ARGB32_OFFSET_R); } \
     529                 :         OUTPUT(GFX_ARGB32_OFFSET_A);
     530                 : #define SUM_PIXEL() \
     531                 :         if (!aAlphaOnly) { SUM(GFX_ARGB32_OFFSET_B); \
     532                 :                            SUM(GFX_ARGB32_OFFSET_G); \
     533                 :                            SUM(GFX_ARGB32_OFFSET_R); } \
     534                 :         SUM(GFX_ARGB32_OFFSET_A);
     535               0 :     for (PRInt32 minor = aStartMinor;
     536                 :          minor < aStartMinor + aLeftLobe;
     537                 :          minor++) {
     538               0 :       OUTPUT_PIXEL();
     539               0 :       SUM_PIXEL();
     540               0 :       nextInput += aStrideMinor;
     541               0 :       aOutput += aStrideMinor;
     542                 :     }
     543               0 :     for (PRInt32 minor = aStartMinor + aLeftLobe;
     544                 :          minor < aEndMinor - aRightLobe - 1;
     545                 :          minor++) {
     546               0 :       OUTPUT_PIXEL();
     547               0 :       SUM_PIXEL();
     548               0 :       lastInput += aStrideMinor;
     549               0 :       nextInput += aStrideMinor;
     550               0 :       aOutput += aStrideMinor;
     551                 :     }
     552                 :     // nextInput is now aInput + aEndMinor*aStrideMinor. Set it back to
     553                 :     // aInput + (aEndMinor - 1)*aStrideMinor so we read the last pixel in every
     554                 :     // iteration of the next loop.
     555               0 :     nextInput -= aStrideMinor;
     556               0 :     for (PRInt32 minor = aEndMinor - aRightLobe - 1; minor < aEndMinor; minor++) {
     557               0 :       OUTPUT_PIXEL();
     558               0 :       SUM_PIXEL();
     559               0 :       lastInput += aStrideMinor;
     560               0 :       aOutput += aStrideMinor;
     561                 : #undef SUM_PIXEL
     562                 : #undef SUM
     563                 :     }
     564                 :   } else {
     565               0 :     for (PRInt32 minor = aStartMinor; minor < aEndMinor; minor++) {
     566               0 :       PRInt32 tmp = minor - aLeftLobe;
     567               0 :       PRInt32 last = NS_MAX(tmp, aStartMinor);
     568               0 :       PRInt32 next = NS_MIN(tmp + PRInt32(boxSize), aEndMinor - 1);
     569                 : 
     570               0 :       OUTPUT_PIXEL();
     571                 : #define SUM(j)     sums[j] += aInput[aStrideMinor*next + j] - \
     572                 :                               aInput[aStrideMinor*last + j];
     573               0 :       if (!aAlphaOnly) { SUM(GFX_ARGB32_OFFSET_B);
     574               0 :                          SUM(GFX_ARGB32_OFFSET_G);
     575               0 :                          SUM(GFX_ARGB32_OFFSET_R); }
     576               0 :       SUM(GFX_ARGB32_OFFSET_A);
     577               0 :       aOutput += aStrideMinor;
     578                 : #undef SUM
     579                 : #undef OUTPUT_PIXEL
     580                 : #undef OUTPUT
     581                 :     }
     582                 :   }
     583               0 : }
     584                 : 
     585                 : static PRUint32
     586               0 : GetBlurBoxSize(double aStdDev)
     587                 : {
     588               0 :   NS_ASSERTION(aStdDev >= 0, "Negative standard deviations not allowed");
     589                 : 
     590               0 :   double size = aStdDev*3*sqrt(2*M_PI)/4;
     591                 :   // Doing super-large blurs accurately isn't very important.
     592               0 :   PRUint32 max = 1024;
     593               0 :   if (size > max)
     594               0 :     return max;
     595               0 :   return PRUint32(floor(size + 0.5));
     596                 : }
     597                 : 
     598                 : nsresult
     599               0 : nsSVGFEGaussianBlurElement::GetDXY(PRUint32 *aDX, PRUint32 *aDY,
     600                 :                                    const nsSVGFilterInstance& aInstance)
     601                 : {
     602                 :   float stdX = aInstance.GetPrimitiveNumber(nsSVGUtils::X,
     603                 :                                             &mNumberPairAttributes[STD_DEV],
     604               0 :                                             nsSVGNumberPair::eFirst);
     605                 :   float stdY = aInstance.GetPrimitiveNumber(nsSVGUtils::Y,
     606                 :                                             &mNumberPairAttributes[STD_DEV],
     607               0 :                                             nsSVGNumberPair::eSecond);
     608               0 :   if (stdX < 0 || stdY < 0)
     609               0 :     return NS_ERROR_FAILURE;
     610                 : 
     611                 :   // If the box size is greater than twice the temporary surface size
     612                 :   // in an axis, then each pixel will be set to the average of all the
     613                 :   // other pixel values.
     614               0 :   *aDX = GetBlurBoxSize(stdX);
     615               0 :   *aDY = GetBlurBoxSize(stdY);
     616               0 :   return NS_OK;
     617                 : }
     618                 : 
     619                 : static bool
     620               0 : AreAllColorChannelsZero(const nsSVGFE::Image* aTarget)
     621                 : {
     622                 :   return aTarget->mConstantColorChannels &&
     623               0 :          aTarget->mImage->GetDataSize() >= 4 &&
     624               0 :          (*reinterpret_cast<PRUint32*>(aTarget->mImage->Data()) & 0x00FFFFFF) == 0;
     625                 : }
     626                 : 
     627                 : void
     628               0 : nsSVGFEGaussianBlurElement::GaussianBlur(const Image *aSource,
     629                 :                                          const Image *aTarget,                                         
     630                 :                                          const nsIntRect& aDataRect,
     631                 :                                          PRUint32 aDX, PRUint32 aDY)
     632                 : {
     633               0 :   NS_ASSERTION(nsIntRect(0, 0, aTarget->mImage->Width(), aTarget->mImage->Height()).Contains(aDataRect),
     634                 :                "aDataRect out of bounds");
     635                 : 
     636               0 :   nsAutoArrayPtr<PRUint8> tmp(new PRUint8[aTarget->mImage->GetDataSize()]);
     637               0 :   if (!tmp)
     638                 :     return;
     639               0 :   memset(tmp, 0, aTarget->mImage->GetDataSize());
     640                 : 
     641               0 :   bool alphaOnly = AreAllColorChannelsZero(aTarget);
     642                 :   
     643               0 :   const PRUint8* sourceData = aSource->mImage->Data();
     644               0 :   PRUint8* targetData = aTarget->mImage->Data();
     645               0 :   PRUint32 stride = aTarget->mImage->Stride();
     646                 : 
     647               0 :   if (aDX == 0) {
     648               0 :     CopyDataRect(tmp, sourceData, stride, aDataRect);
     649                 :   } else {
     650               0 :     PRInt32 longLobe = aDX/2;
     651               0 :     PRInt32 shortLobe = (aDX & 1) ? longLobe : longLobe - 1;
     652               0 :     for (PRInt32 major = aDataRect.y; major < aDataRect.YMost(); ++major) {
     653               0 :       PRInt32 ms = major*stride;
     654               0 :       BoxBlur(sourceData + ms, tmp + ms, 4, aDataRect.x, aDataRect.XMost(), longLobe, shortLobe, alphaOnly);
     655               0 :       BoxBlur(tmp + ms, targetData + ms, 4, aDataRect.x, aDataRect.XMost(), shortLobe, longLobe, alphaOnly);
     656               0 :       BoxBlur(targetData + ms, tmp + ms, 4, aDataRect.x, aDataRect.XMost(), longLobe, longLobe, alphaOnly);
     657                 :     }
     658                 :   }
     659                 : 
     660               0 :   if (aDY == 0) {
     661               0 :     CopyDataRect(targetData, tmp, stride, aDataRect);
     662                 :   } else {
     663               0 :     PRInt32 longLobe = aDY/2;
     664               0 :     PRInt32 shortLobe = (aDY & 1) ? longLobe : longLobe - 1;
     665               0 :     for (PRInt32 major = aDataRect.x; major < aDataRect.XMost(); ++major) {
     666               0 :       PRInt32 ms = major*4;
     667               0 :       BoxBlur(tmp + ms, targetData + ms, stride, aDataRect.y, aDataRect.YMost(), longLobe, shortLobe, alphaOnly);
     668               0 :       BoxBlur(targetData + ms, tmp + ms, stride, aDataRect.y, aDataRect.YMost(), shortLobe, longLobe, alphaOnly);
     669               0 :       BoxBlur(tmp + ms, targetData + ms, stride, aDataRect.y, aDataRect.YMost(), longLobe, longLobe, alphaOnly);
     670                 :     }
     671                 :   }
     672                 : }
     673                 : 
     674                 : static void
     675               0 : InflateRectForBlurDXY(nsIntRect* aRect, PRUint32 aDX, PRUint32 aDY)
     676                 : {
     677               0 :   aRect->Inflate(3*(aDX/2), 3*(aDY/2));
     678               0 : }
     679                 : 
     680                 : static void
     681               0 : ClearRect(gfxImageSurface* aSurface, PRInt32 aX, PRInt32 aY,
     682                 :           PRInt32 aXMost, PRInt32 aYMost)
     683                 : {
     684               0 :   NS_ASSERTION(aX <= aXMost && aY <= aYMost, "Invalid rectangle");
     685               0 :   NS_ASSERTION(aX >= 0 && aY >= 0 && aXMost <= aSurface->Width() && aYMost <= aSurface->Height(),
     686                 :                "Rectangle out of bounds");
     687                 : 
     688               0 :   if (aX == aXMost || aY == aYMost)
     689               0 :     return;
     690               0 :   for (PRInt32 y = aY; y < aYMost; ++y) {
     691               0 :     memset(aSurface->Data() + aSurface->Stride()*y + aX*4, 0, (aXMost - aX)*4);
     692                 :   }
     693                 : }
     694                 : 
     695                 : // Clip aTarget's image to its filter primitive subregion.
     696                 : // aModifiedRect contains all the pixels which might not be RGBA(0,0,0,0),
     697                 : // it's relative to the surface data.
     698                 : static void
     699               0 : ClipTarget(nsSVGFilterInstance* aInstance, const nsSVGFE::Image* aTarget,
     700                 :            const nsIntRect& aModifiedRect)
     701                 : {
     702               0 :   nsIntPoint surfaceTopLeft = aInstance->GetSurfaceRect().TopLeft();
     703                 : 
     704               0 :   NS_ASSERTION(aInstance->GetSurfaceRect().Contains(aModifiedRect + surfaceTopLeft),
     705                 :                "Modified data area overflows the surface?");
     706                 : 
     707               0 :   nsIntRect clip = aModifiedRect;
     708                 :   nsSVGUtils::ClipToGfxRect(&clip,
     709               0 :     aTarget->mFilterPrimitiveSubregion - gfxPoint(surfaceTopLeft.x, surfaceTopLeft.y));
     710                 : 
     711               0 :   ClearRect(aTarget->mImage, aModifiedRect.x, aModifiedRect.y, aModifiedRect.XMost(), clip.y);
     712               0 :   ClearRect(aTarget->mImage, aModifiedRect.x, clip.y, clip.x, clip.YMost());
     713               0 :   ClearRect(aTarget->mImage, clip.XMost(), clip.y, aModifiedRect.XMost(), clip.YMost());
     714               0 :   ClearRect(aTarget->mImage, aModifiedRect.x, clip.YMost(), aModifiedRect.XMost(), aModifiedRect.YMost());
     715               0 : }
     716                 : 
     717                 : static void
     718               0 : ClipComputationRectToSurface(nsSVGFilterInstance* aInstance,
     719                 :                              nsIntRect* aDataRect)
     720                 : {
     721                 :   aDataRect->IntersectRect(*aDataRect,
     722               0 :           nsIntRect(nsIntPoint(0, 0), aInstance->GetSurfaceRect().Size()));
     723               0 : }
     724                 : 
     725                 : nsresult
     726               0 : nsSVGFEGaussianBlurElement::Filter(nsSVGFilterInstance* aInstance,
     727                 :                                    const nsTArray<const Image*>& aSources,
     728                 :                                    const Image* aTarget,
     729                 :                                    const nsIntRect& rect)
     730                 : {
     731                 :   PRUint32 dx, dy;
     732               0 :   nsresult rv = GetDXY(&dx, &dy, *aInstance);
     733               0 :   if (NS_FAILED(rv))
     734               0 :     return rv;
     735                 : 
     736               0 :   nsIntRect computationRect = rect;
     737               0 :   InflateRectForBlurDXY(&computationRect, dx, dy);
     738               0 :   ClipComputationRectToSurface(aInstance, &computationRect);
     739               0 :   GaussianBlur(aSources[0], aTarget, computationRect, dx, dy);
     740               0 :   ClipTarget(aInstance, aTarget, computationRect);
     741               0 :   return NS_OK;
     742                 : }
     743                 : 
     744                 : bool
     745               0 : nsSVGFEGaussianBlurElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
     746                 :                                                       nsIAtom* aAttribute) const
     747                 : {
     748               0 :   return nsSVGFEGaussianBlurElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
     749                 :          (aNameSpaceID == kNameSpaceID_None &&
     750                 :           (aAttribute == nsGkAtoms::in ||
     751               0 :            aAttribute == nsGkAtoms::stdDeviation));
     752                 : }
     753                 : 
     754                 : void
     755               0 : nsSVGFEGaussianBlurElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
     756                 : {
     757               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
     758               0 : }
     759                 : 
     760                 : nsIntRect
     761               0 : nsSVGFEGaussianBlurElement::InflateRectForBlur(const nsIntRect& aRect,
     762                 :                                                const nsSVGFilterInstance& aInstance)
     763                 : {
     764                 :   PRUint32 dX, dY;
     765               0 :   nsresult rv = GetDXY(&dX, &dY, aInstance);
     766               0 :   nsIntRect result = aRect;
     767               0 :   if (NS_SUCCEEDED(rv)) {
     768               0 :     InflateRectForBlurDXY(&result, dX, dY);
     769                 :   }
     770                 :   return result;
     771                 : }
     772                 : 
     773                 : nsIntRect
     774               0 : nsSVGFEGaussianBlurElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
     775                 :         const nsSVGFilterInstance& aInstance)
     776                 : {
     777               0 :   return InflateRectForBlur(aSourceBBoxes[0], aInstance);
     778                 : }
     779                 : 
     780                 : void
     781               0 : nsSVGFEGaussianBlurElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
     782                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
     783                 : {
     784               0 :   aSourceBBoxes[0] = InflateRectForBlur(aTargetBBox, aInstance);
     785               0 : }
     786                 : 
     787                 : nsIntRect
     788               0 : nsSVGFEGaussianBlurElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
     789                 :                                               const nsSVGFilterInstance& aInstance)
     790                 : {
     791               0 :   return InflateRectForBlur(aSourceChangeBoxes[0], aInstance);
     792                 : }
     793                 : 
     794                 : //----------------------------------------------------------------------
     795                 : // nsSVGElement methods
     796                 : 
     797                 : nsSVGElement::NumberPairAttributesInfo
     798               0 : nsSVGFEGaussianBlurElement::GetNumberPairInfo()
     799                 : {
     800                 :   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
     801               0 :                                   ArrayLength(sNumberPairInfo));
     802                 : }
     803                 : 
     804                 : nsSVGElement::StringAttributesInfo
     805               0 : nsSVGFEGaussianBlurElement::GetStringInfo()
     806                 : {
     807                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
     808               0 :                               ArrayLength(sStringInfo));
     809                 : }
     810                 : 
     811                 : //---------------------Blend------------------------
     812                 : 
     813                 : typedef nsSVGFE nsSVGFEBlendElementBase;
     814                 : 
     815                 : class nsSVGFEBlendElement : public nsSVGFEBlendElementBase,
     816                 :                             public nsIDOMSVGFEBlendElement
     817               0 : {
     818                 :   friend nsresult NS_NewSVGFEBlendElement(nsIContent **aResult,
     819                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
     820                 : protected:
     821               0 :   nsSVGFEBlendElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     822               0 :     : nsSVGFEBlendElementBase(aNodeInfo) {}
     823                 : 
     824                 : public:
     825                 :   // interfaces:
     826                 :   NS_DECL_ISUPPORTS_INHERITED
     827                 : 
     828                 :   // FE Base
     829               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEBlendElementBase::)
     830                 : 
     831                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
     832                 :                           const nsTArray<const Image*>& aSources,
     833                 :                           const Image* aTarget,
     834                 :                           const nsIntRect& aDataRect);
     835                 :   virtual bool AttributeAffectsRendering(
     836                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
     837               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
     838                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
     839                 : 
     840                 :   // Blend
     841                 :   NS_DECL_NSIDOMSVGFEBLENDELEMENT
     842                 : 
     843               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEBlendElementBase::)
     844                 : 
     845               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEBlendElementBase::)
     846               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEBlendElementBase::)
     847                 : 
     848                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
     849                 : 
     850                 :   virtual nsXPCClassInfo* GetClassInfo();
     851                 : protected:
     852                 : 
     853                 :   virtual EnumAttributesInfo GetEnumInfo();
     854                 :   virtual StringAttributesInfo GetStringInfo();
     855                 : 
     856                 :   enum { MODE };
     857                 :   nsSVGEnum mEnumAttributes[1];
     858                 :   static nsSVGEnumMapping sModeMap[];
     859                 :   static EnumInfo sEnumInfo[1];
     860                 : 
     861                 :   enum { RESULT, IN1, IN2 };
     862                 :   nsSVGString mStringAttributes[3];
     863                 :   static StringInfo sStringInfo[3];
     864                 : };
     865                 : 
     866                 : nsSVGEnumMapping nsSVGFEBlendElement::sModeMap[] = {
     867                 :   {&nsGkAtoms::normal, nsSVGFEBlendElement::SVG_MODE_NORMAL},
     868                 :   {&nsGkAtoms::multiply, nsSVGFEBlendElement::SVG_MODE_MULTIPLY},
     869                 :   {&nsGkAtoms::screen, nsSVGFEBlendElement::SVG_MODE_SCREEN},
     870                 :   {&nsGkAtoms::darken, nsSVGFEBlendElement::SVG_MODE_DARKEN},
     871                 :   {&nsGkAtoms::lighten, nsSVGFEBlendElement::SVG_MODE_LIGHTEN},
     872                 :   {nsnull, 0}
     873                 : };
     874                 : 
     875                 : nsSVGElement::EnumInfo nsSVGFEBlendElement::sEnumInfo[1] =
     876                 : {
     877                 :   { &nsGkAtoms::mode,
     878                 :     sModeMap,
     879                 :     nsSVGFEBlendElement::SVG_MODE_NORMAL
     880                 :   }
     881                 : };
     882                 : 
     883                 : nsSVGElement::StringInfo nsSVGFEBlendElement::sStringInfo[3] =
     884                 : {
     885                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
     886                 :   { &nsGkAtoms::in, kNameSpaceID_None, true },
     887                 :   { &nsGkAtoms::in2, kNameSpaceID_None, true }
     888                 : };
     889                 : 
     890               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEBlend)
     891                 : 
     892                 : //----------------------------------------------------------------------
     893                 : // nsISupports methods
     894                 : 
     895               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEBlendElement,nsSVGFEBlendElementBase)
     896               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEBlendElement,nsSVGFEBlendElementBase)
     897                 : 
     898               0 : DOMCI_NODE_DATA(SVGFEBlendElement, nsSVGFEBlendElement)
     899                 : 
     900               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEBlendElement)
     901               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEBlendElement, nsIDOMNode, nsIDOMElement,
     902                 :                            nsIDOMSVGElement,
     903                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
     904                 :                            nsIDOMSVGFEBlendElement)
     905               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEBlendElement)
     906               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBlendElementBase)
     907                 : 
     908                 : //----------------------------------------------------------------------
     909                 : // nsIDOMNode methods
     910                 : 
     911                 : 
     912               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEBlendElement)
     913                 : 
     914                 : //----------------------------------------------------------------------
     915                 : // nsIDOMSVGFEBlendElement methods
     916                 : 
     917                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
     918               0 : NS_IMETHODIMP nsSVGFEBlendElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
     919                 : {
     920               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
     921                 : }
     922                 : 
     923                 : /* readonly attribute nsIDOMSVGAnimatedString in2; */
     924               0 : NS_IMETHODIMP nsSVGFEBlendElement::GetIn2(nsIDOMSVGAnimatedString * *aIn)
     925                 : {
     926               0 :   return mStringAttributes[IN2].ToDOMAnimatedString(aIn, this);
     927                 : }
     928                 : 
     929                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration mode; */
     930               0 : NS_IMETHODIMP nsSVGFEBlendElement::GetMode(nsIDOMSVGAnimatedEnumeration * *aMode)
     931                 : {
     932               0 :   return mEnumAttributes[MODE].ToDOMAnimatedEnum(aMode, this);
     933                 : }
     934                 : 
     935                 : nsresult
     936               0 : nsSVGFEBlendElement::Filter(nsSVGFilterInstance* aInstance,
     937                 :                             const nsTArray<const Image*>& aSources,
     938                 :                             const Image* aTarget,
     939                 :                             const nsIntRect& rect)
     940                 : {
     941               0 :   CopyRect(aTarget, aSources[0], rect);
     942                 : 
     943               0 :   PRUint8* sourceData = aSources[1]->mImage->Data();
     944               0 :   PRUint8* targetData = aTarget->mImage->Data();
     945               0 :   PRUint32 stride = aTarget->mImage->Stride();
     946                 : 
     947               0 :   PRUint16 mode = mEnumAttributes[MODE].GetAnimValue();
     948                 : 
     949               0 :   for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
     950               0 :     for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
     951               0 :       PRUint32 targIndex = y * stride + 4 * x;
     952               0 :       PRUint32 qa = targetData[targIndex + GFX_ARGB32_OFFSET_A];
     953               0 :       PRUint32 qb = sourceData[targIndex + GFX_ARGB32_OFFSET_A];
     954               0 :       for (PRInt32 i = NS_MIN(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R);
     955               0 :            i <= NS_MAX(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R); i++) {
     956               0 :         PRUint32 ca = targetData[targIndex + i];
     957               0 :         PRUint32 cb = sourceData[targIndex + i];
     958                 :         PRUint32 val;
     959               0 :         switch (mode) {
     960                 :           case nsSVGFEBlendElement::SVG_MODE_NORMAL:
     961               0 :             val = (255 - qa) * cb + 255 * ca;
     962               0 :             break;
     963                 :           case nsSVGFEBlendElement::SVG_MODE_MULTIPLY:
     964               0 :             val = ((255 - qa) * cb + (255 - qb + cb) * ca);
     965               0 :             break;
     966                 :           case nsSVGFEBlendElement::SVG_MODE_SCREEN:
     967               0 :             val = 255 * (cb + ca) - ca * cb;
     968               0 :             break;
     969                 :           case nsSVGFEBlendElement::SVG_MODE_DARKEN:
     970                 :             val = NS_MIN((255 - qa) * cb + 255 * ca,
     971               0 :                          (255 - qb) * ca + 255 * cb);
     972               0 :             break;
     973                 :           case nsSVGFEBlendElement::SVG_MODE_LIGHTEN:
     974                 :             val = NS_MAX((255 - qa) * cb + 255 * ca,
     975               0 :                          (255 - qb) * ca + 255 * cb);
     976               0 :             break;
     977                 :           default:
     978               0 :             return NS_ERROR_FAILURE;
     979                 :             break;
     980                 :         }
     981               0 :         val = NS_MIN(val / 255, 255U);
     982               0 :         targetData[targIndex + i] =  static_cast<PRUint8>(val);
     983                 :       }
     984               0 :       PRUint32 alpha = 255 * 255 - (255 - qa) * (255 - qb);
     985               0 :       FAST_DIVIDE_BY_255(targetData[targIndex + GFX_ARGB32_OFFSET_A], alpha);
     986                 :     }
     987                 :   }
     988               0 :   return NS_OK;
     989                 : }
     990                 : 
     991                 : bool
     992               0 : nsSVGFEBlendElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
     993                 :                                                nsIAtom* aAttribute) const
     994                 : {
     995               0 :   return nsSVGFEBlendElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
     996                 :          (aNameSpaceID == kNameSpaceID_None &&
     997                 :           (aAttribute == nsGkAtoms::in ||
     998                 :            aAttribute == nsGkAtoms::in2 ||
     999               0 :            aAttribute == nsGkAtoms::mode));
    1000                 : }
    1001                 : 
    1002                 : void
    1003               0 : nsSVGFEBlendElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    1004                 : {
    1005               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    1006               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
    1007               0 : }
    1008                 : 
    1009                 : //----------------------------------------------------------------------
    1010                 : // nsSVGElement methods
    1011                 : 
    1012                 : nsSVGElement::EnumAttributesInfo
    1013               0 : nsSVGFEBlendElement::GetEnumInfo()
    1014                 : {
    1015                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    1016               0 :                             ArrayLength(sEnumInfo));
    1017                 : }
    1018                 : 
    1019                 : nsSVGElement::StringAttributesInfo
    1020               0 : nsSVGFEBlendElement::GetStringInfo()
    1021                 : {
    1022                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    1023               0 :                               ArrayLength(sStringInfo));
    1024                 : }
    1025                 : 
    1026                 : //---------------------Color Matrix------------------------
    1027                 : 
    1028                 : typedef nsSVGFE nsSVGFEColorMatrixElementBase;
    1029                 : 
    1030                 : class nsSVGFEColorMatrixElement : public nsSVGFEColorMatrixElementBase,
    1031                 :                                   public nsIDOMSVGFEColorMatrixElement
    1032               0 : {
    1033                 :   friend nsresult NS_NewSVGFEColorMatrixElement(nsIContent **aResult,
    1034                 :                                                 already_AddRefed<nsINodeInfo> aNodeInfo);
    1035                 : protected:
    1036               0 :   nsSVGFEColorMatrixElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    1037               0 :     : nsSVGFEColorMatrixElementBase(aNodeInfo) {}
    1038                 : 
    1039                 : public:
    1040                 :   // interfaces:
    1041                 :   NS_DECL_ISUPPORTS_INHERITED
    1042                 : 
    1043                 :   // FE Base
    1044               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEColorMatrixElementBase::)
    1045                 : 
    1046                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    1047                 :                           const nsTArray<const Image*>& aSources,
    1048                 :                           const Image* aTarget,
    1049                 :                           const nsIntRect& aDataRect);
    1050                 :   virtual bool AttributeAffectsRendering(
    1051                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    1052               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    1053                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    1054                 : 
    1055                 :   // Color Matrix
    1056                 :   NS_DECL_NSIDOMSVGFECOLORMATRIXELEMENT
    1057                 : 
    1058               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEColorMatrixElementBase::)
    1059                 : 
    1060               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEColorMatrixElementBase::)
    1061               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEColorMatrixElementBase::)
    1062                 : 
    1063                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    1064                 : 
    1065                 :   virtual nsXPCClassInfo* GetClassInfo();
    1066                 : protected:
    1067               0 :   virtual bool OperatesOnPremultipledAlpha(PRInt32) { return false; }
    1068                 : 
    1069                 :   virtual EnumAttributesInfo GetEnumInfo();
    1070                 :   virtual StringAttributesInfo GetStringInfo();
    1071                 :   virtual NumberListAttributesInfo GetNumberListInfo();
    1072                 : 
    1073                 :   enum { TYPE };
    1074                 :   nsSVGEnum mEnumAttributes[1];
    1075                 :   static nsSVGEnumMapping sTypeMap[];
    1076                 :   static EnumInfo sEnumInfo[1];
    1077                 : 
    1078                 :   enum { RESULT, IN1 };
    1079                 :   nsSVGString mStringAttributes[2];
    1080                 :   static StringInfo sStringInfo[2];
    1081                 : 
    1082                 :   enum { VALUES };
    1083                 :   SVGAnimatedNumberList mNumberListAttributes[1];
    1084                 :   static NumberListInfo sNumberListInfo[1];
    1085                 : };
    1086                 : 
    1087                 : nsSVGEnumMapping nsSVGFEColorMatrixElement::sTypeMap[] = {
    1088                 :   {&nsGkAtoms::matrix, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX},
    1089                 :   {&nsGkAtoms::saturate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE},
    1090                 :   {&nsGkAtoms::hueRotate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE},
    1091                 :   {&nsGkAtoms::luminanceToAlpha, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA},
    1092                 :   {nsnull, 0}
    1093                 : };
    1094                 : 
    1095                 : nsSVGElement::EnumInfo nsSVGFEColorMatrixElement::sEnumInfo[1] =
    1096                 : {
    1097                 :   { &nsGkAtoms::type,
    1098                 :     sTypeMap,
    1099                 :     nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX
    1100                 :   }
    1101                 : };
    1102                 : 
    1103                 : nsSVGElement::StringInfo nsSVGFEColorMatrixElement::sStringInfo[2] =
    1104                 : {
    1105                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    1106                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    1107                 : };
    1108                 : 
    1109                 : nsSVGElement::NumberListInfo nsSVGFEColorMatrixElement::sNumberListInfo[1] =
    1110                 : {
    1111                 :   { &nsGkAtoms::values }
    1112                 : };
    1113                 : 
    1114               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEColorMatrix)
    1115                 : 
    1116                 : //----------------------------------------------------------------------
    1117                 : // nsISupports methods
    1118                 : 
    1119               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase)
    1120               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase)
    1121                 : 
    1122               0 : DOMCI_NODE_DATA(SVGFEColorMatrixElement, nsSVGFEColorMatrixElement)
    1123                 : 
    1124               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEColorMatrixElement)
    1125               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEColorMatrixElement, nsIDOMNode, nsIDOMElement,
    1126                 :                            nsIDOMSVGElement,
    1127                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    1128                 :                            nsIDOMSVGFEColorMatrixElement)
    1129               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEColorMatrixElement)
    1130               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEColorMatrixElementBase)
    1131                 : 
    1132                 : 
    1133                 : //----------------------------------------------------------------------
    1134                 : // nsIDOMNode methods
    1135                 : 
    1136                 : 
    1137               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEColorMatrixElement)
    1138                 : 
    1139                 : 
    1140                 : //----------------------------------------------------------------------
    1141                 : // nsSVGFEColorMatrixElement methods
    1142                 : 
    1143                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    1144               0 : NS_IMETHODIMP nsSVGFEColorMatrixElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    1145                 : {
    1146               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    1147                 : }
    1148                 : 
    1149                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
    1150               0 : NS_IMETHODIMP nsSVGFEColorMatrixElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
    1151                 : {
    1152               0 :   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
    1153                 : }
    1154                 : 
    1155                 : /* readonly attribute nsIDOMSVGAnimatedNumberList values; */
    1156               0 : NS_IMETHODIMP nsSVGFEColorMatrixElement::GetValues(nsIDOMSVGAnimatedNumberList * *aValues)
    1157                 : {
    1158                 :   *aValues = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[VALUES],
    1159               0 :                                                      this, VALUES).get();
    1160               0 :   return NS_OK;
    1161                 : }
    1162                 : 
    1163                 : void
    1164               0 : nsSVGFEColorMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    1165                 : {
    1166               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    1167               0 : }
    1168                 : 
    1169                 : nsresult
    1170               0 : nsSVGFEColorMatrixElement::Filter(nsSVGFilterInstance *instance,
    1171                 :                                   const nsTArray<const Image*>& aSources,
    1172                 :                                   const Image* aTarget,
    1173                 :                                   const nsIntRect& rect)
    1174                 : {
    1175               0 :   PRUint8* sourceData = aSources[0]->mImage->Data();
    1176               0 :   PRUint8* targetData = aTarget->mImage->Data();
    1177               0 :   PRUint32 stride = aTarget->mImage->Stride();
    1178                 : 
    1179               0 :   PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
    1180               0 :   const SVGNumberList &values = mNumberListAttributes[VALUES].GetAnimValue();
    1181                 : 
    1182               0 :   if (!mNumberListAttributes[VALUES].IsExplicitlySet() &&
    1183                 :       (type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX ||
    1184                 :        type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE ||
    1185                 :        type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE)) {
    1186                 :     // identity matrix filter
    1187               0 :     CopyRect(aTarget, aSources[0], rect);
    1188               0 :     return NS_OK;
    1189                 :   }
    1190                 : 
    1191                 :   static const float identityMatrix[] = 
    1192                 :     { 1, 0, 0, 0, 0,
    1193                 :       0, 1, 0, 0, 0,
    1194                 :       0, 0, 1, 0, 0,
    1195                 :       0, 0, 0, 1, 0 };
    1196                 : 
    1197                 :   static const float luminanceToAlphaMatrix[] = 
    1198                 :     { 0,       0,       0,       0, 0,
    1199                 :       0,       0,       0,       0, 0,
    1200                 :       0,       0,       0,       0, 0,
    1201                 :       0.2125f, 0.7154f, 0.0721f, 0, 0 };
    1202                 : 
    1203                 :   float colorMatrix[NUM_ENTRIES_IN_4x5_MATRIX];
    1204                 :   float s, c;
    1205                 : 
    1206               0 :   switch (type) {
    1207                 :   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX:
    1208                 : 
    1209               0 :     if (values.Length() != NUM_ENTRIES_IN_4x5_MATRIX)
    1210               0 :       return NS_ERROR_FAILURE;
    1211                 : 
    1212               0 :     for(PRUint32 j = 0; j < values.Length(); j++) {
    1213               0 :       colorMatrix[j] = values[j];
    1214                 :     }
    1215               0 :     break;
    1216                 :   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE:
    1217                 : 
    1218               0 :     if (values.Length() != 1)
    1219               0 :       return NS_ERROR_FAILURE;
    1220                 : 
    1221               0 :     s = values[0];
    1222                 : 
    1223               0 :     if (s > 1 || s < 0)
    1224               0 :       return NS_ERROR_FAILURE;
    1225                 : 
    1226               0 :     memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
    1227                 : 
    1228               0 :     colorMatrix[0] = 0.213f + 0.787f * s;
    1229               0 :     colorMatrix[1] = 0.715f - 0.715f * s;
    1230               0 :     colorMatrix[2] = 0.072f - 0.072f * s;
    1231                 : 
    1232               0 :     colorMatrix[5] = 0.213f - 0.213f * s;
    1233               0 :     colorMatrix[6] = 0.715f + 0.285f * s;
    1234               0 :     colorMatrix[7] = 0.072f - 0.072f * s;
    1235                 : 
    1236               0 :     colorMatrix[10] = 0.213f - 0.213f * s;
    1237               0 :     colorMatrix[11] = 0.715f - 0.715f * s;
    1238               0 :     colorMatrix[12] = 0.072f + 0.928f * s;
    1239                 : 
    1240               0 :     break;
    1241                 : 
    1242                 :   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE:
    1243                 :   {
    1244               0 :     memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
    1245                 : 
    1246               0 :     if (values.Length() != 1)
    1247               0 :       return NS_ERROR_FAILURE;
    1248                 : 
    1249               0 :     float hueRotateValue = values[0];
    1250                 : 
    1251               0 :     c = static_cast<float>(cos(hueRotateValue * M_PI / 180));
    1252               0 :     s = static_cast<float>(sin(hueRotateValue * M_PI / 180));
    1253                 : 
    1254               0 :     memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
    1255                 : 
    1256               0 :     colorMatrix[0] = 0.213f + 0.787f * c - 0.213f * s;
    1257               0 :     colorMatrix[1] = 0.715f - 0.715f * c - 0.715f * s;
    1258               0 :     colorMatrix[2] = 0.072f - 0.072f * c + 0.928f * s;
    1259                 : 
    1260               0 :     colorMatrix[5] = 0.213f - 0.213f * c + 0.143f * s;
    1261               0 :     colorMatrix[6] = 0.715f + 0.285f * c + 0.140f * s;
    1262               0 :     colorMatrix[7] = 0.072f - 0.072f * c - 0.283f * s;
    1263                 : 
    1264               0 :     colorMatrix[10] = 0.213f - 0.213f * c - 0.787f * s;
    1265               0 :     colorMatrix[11] = 0.715f - 0.715f * c + 0.715f * s;
    1266               0 :     colorMatrix[12] = 0.072f + 0.928f * c + 0.072f * s;
    1267                 : 
    1268               0 :     break;
    1269                 :   }
    1270                 : 
    1271                 :   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA:
    1272                 : 
    1273               0 :     memcpy(colorMatrix, luminanceToAlphaMatrix, sizeof(colorMatrix));
    1274               0 :     break;
    1275                 : 
    1276                 :   default:
    1277               0 :     return NS_ERROR_FAILURE;
    1278                 :   }
    1279                 : 
    1280               0 :   for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    1281               0 :     for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    1282               0 :       PRUint32 targIndex = y * stride + 4 * x;
    1283                 : 
    1284                 :       float col[4];
    1285               0 :       for (int i = 0, row = 0; i < 4; i++, row += 5) {
    1286                 :         col[i] =
    1287               0 :           sourceData[targIndex + GFX_ARGB32_OFFSET_R] * colorMatrix[row + 0] +
    1288               0 :           sourceData[targIndex + GFX_ARGB32_OFFSET_G] * colorMatrix[row + 1] +
    1289               0 :           sourceData[targIndex + GFX_ARGB32_OFFSET_B] * colorMatrix[row + 2] +
    1290               0 :           sourceData[targIndex + GFX_ARGB32_OFFSET_A] * colorMatrix[row + 3] +
    1291               0 :           255 *                                         colorMatrix[row + 4];
    1292               0 :         col[i] = clamped(col[i], 0.f, 255.f);
    1293                 :       }
    1294               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_R] =
    1295               0 :         static_cast<PRUint8>(col[0]);
    1296               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_G] =
    1297               0 :         static_cast<PRUint8>(col[1]);
    1298               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_B] =
    1299               0 :         static_cast<PRUint8>(col[2]);
    1300               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_A] =
    1301               0 :         static_cast<PRUint8>(col[3]);
    1302                 :     }
    1303                 :   }
    1304               0 :   return NS_OK;
    1305                 : }
    1306                 : 
    1307                 : bool
    1308               0 : nsSVGFEColorMatrixElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    1309                 :                                                      nsIAtom* aAttribute) const
    1310                 : {
    1311               0 :   return nsSVGFEColorMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    1312                 :          (aNameSpaceID == kNameSpaceID_None &&
    1313                 :           (aAttribute == nsGkAtoms::in ||
    1314                 :            aAttribute == nsGkAtoms::type ||
    1315               0 :            aAttribute == nsGkAtoms::values));
    1316                 : }
    1317                 : 
    1318                 : //----------------------------------------------------------------------
    1319                 : // nsSVGElement methods
    1320                 : 
    1321                 : nsSVGElement::EnumAttributesInfo
    1322               0 : nsSVGFEColorMatrixElement::GetEnumInfo()
    1323                 : {
    1324                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    1325               0 :                             ArrayLength(sEnumInfo));
    1326                 : }
    1327                 : 
    1328                 : nsSVGElement::StringAttributesInfo
    1329               0 : nsSVGFEColorMatrixElement::GetStringInfo()
    1330                 : {
    1331                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    1332               0 :                               ArrayLength(sStringInfo));
    1333                 : }
    1334                 : 
    1335                 : nsSVGElement::NumberListAttributesInfo
    1336               0 : nsSVGFEColorMatrixElement::GetNumberListInfo()
    1337                 : {
    1338                 :   return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
    1339               0 :                                   ArrayLength(sNumberListInfo));
    1340                 : }
    1341                 : 
    1342                 : //---------------------Composite------------------------
    1343                 : 
    1344                 : typedef nsSVGFE nsSVGFECompositeElementBase;
    1345                 : 
    1346                 : class nsSVGFECompositeElement : public nsSVGFECompositeElementBase,
    1347                 :                                 public nsIDOMSVGFECompositeElement
    1348               0 : {
    1349                 :   friend nsresult NS_NewSVGFECompositeElement(nsIContent **aResult,
    1350                 :                                               already_AddRefed<nsINodeInfo> aNodeInfo);
    1351                 : protected:
    1352               0 :   nsSVGFECompositeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    1353               0 :     : nsSVGFECompositeElementBase(aNodeInfo) {}
    1354                 : 
    1355                 : public:
    1356                 :   // interfaces:
    1357                 :   NS_DECL_ISUPPORTS_INHERITED
    1358                 : 
    1359                 :   // FE Base
    1360               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFECompositeElementBase::)
    1361                 : 
    1362                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    1363                 :                           const nsTArray<const Image*>& aSources,
    1364                 :                           const Image* aTarget,
    1365                 :                           const nsIntRect& aDataRect);
    1366                 :   virtual bool AttributeAffectsRendering(
    1367                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    1368               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    1369                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    1370                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    1371                 :           const nsSVGFilterInstance& aInstance);
    1372                 : 
    1373                 :   // Composite
    1374                 :   NS_DECL_NSIDOMSVGFECOMPOSITEELEMENT
    1375                 : 
    1376               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFECompositeElementBase::)
    1377                 : 
    1378               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFECompositeElementBase::)
    1379               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFECompositeElementBase::)
    1380                 : 
    1381                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    1382                 : 
    1383                 :   virtual nsXPCClassInfo* GetClassInfo();
    1384                 : protected:
    1385                 :   virtual NumberAttributesInfo GetNumberInfo();
    1386                 :   virtual EnumAttributesInfo GetEnumInfo();
    1387                 :   virtual StringAttributesInfo GetStringInfo();
    1388                 : 
    1389                 :   enum { K1, K2, K3, K4 };
    1390                 :   nsSVGNumber2 mNumberAttributes[4];
    1391                 :   static NumberInfo sNumberInfo[4];
    1392                 : 
    1393                 :   enum { OPERATOR };
    1394                 :   nsSVGEnum mEnumAttributes[1];
    1395                 :   static nsSVGEnumMapping sOperatorMap[];
    1396                 :   static EnumInfo sEnumInfo[1];
    1397                 : 
    1398                 :   enum { RESULT, IN1, IN2 };
    1399                 :   nsSVGString mStringAttributes[3];
    1400                 :   static StringInfo sStringInfo[3];
    1401                 : };
    1402                 : 
    1403                 : nsSVGElement::NumberInfo nsSVGFECompositeElement::sNumberInfo[4] =
    1404                 : {
    1405                 :   { &nsGkAtoms::k1, 0, false },
    1406                 :   { &nsGkAtoms::k2, 0, false },
    1407                 :   { &nsGkAtoms::k3, 0, false },
    1408                 :   { &nsGkAtoms::k4, 0, false }
    1409                 : };
    1410                 : 
    1411                 : nsSVGEnumMapping nsSVGFECompositeElement::sOperatorMap[] = {
    1412                 :   {&nsGkAtoms::over, nsSVGFECompositeElement::SVG_OPERATOR_OVER},
    1413                 :   {&nsGkAtoms::in, nsSVGFECompositeElement::SVG_OPERATOR_IN},
    1414                 :   {&nsGkAtoms::out, nsSVGFECompositeElement::SVG_OPERATOR_OUT},
    1415                 :   {&nsGkAtoms::atop, nsSVGFECompositeElement::SVG_OPERATOR_ATOP},
    1416                 :   {&nsGkAtoms::xor_, nsSVGFECompositeElement::SVG_OPERATOR_XOR},
    1417                 :   {&nsGkAtoms::arithmetic, nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC},
    1418                 :   {nsnull, 0}
    1419                 : };
    1420                 : 
    1421                 : nsSVGElement::EnumInfo nsSVGFECompositeElement::sEnumInfo[1] =
    1422                 : {
    1423                 :   { &nsGkAtoms::_operator,
    1424                 :     sOperatorMap,
    1425                 :     nsIDOMSVGFECompositeElement::SVG_OPERATOR_OVER
    1426                 :   }
    1427                 : };
    1428                 : 
    1429                 : nsSVGElement::StringInfo nsSVGFECompositeElement::sStringInfo[3] =
    1430                 : {
    1431                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    1432                 :   { &nsGkAtoms::in, kNameSpaceID_None, true },
    1433                 :   { &nsGkAtoms::in2, kNameSpaceID_None, true }
    1434                 : };
    1435                 : 
    1436               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEComposite)
    1437                 : 
    1438                 : //----------------------------------------------------------------------
    1439                 : // nsISupports methods
    1440                 : 
    1441               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFECompositeElement,nsSVGFECompositeElementBase)
    1442               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFECompositeElement,nsSVGFECompositeElementBase)
    1443                 : 
    1444               0 : DOMCI_NODE_DATA(SVGFECompositeElement, nsSVGFECompositeElement)
    1445                 : 
    1446               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFECompositeElement)
    1447               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFECompositeElement, nsIDOMNode, nsIDOMElement,
    1448                 :                            nsIDOMSVGElement,
    1449                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    1450                 :                            nsIDOMSVGFECompositeElement)
    1451               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFECompositeElement)
    1452               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFECompositeElementBase)
    1453                 : 
    1454                 : //----------------------------------------------------------------------
    1455                 : // nsIDOMNode methods
    1456                 : 
    1457               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFECompositeElement)
    1458                 : 
    1459                 : //----------------------------------------------------------------------
    1460                 : // nsSVGFECompositeElement methods
    1461                 : 
    1462                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    1463               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    1464                 : {
    1465               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    1466                 : }
    1467                 : 
    1468                 : /* readonly attribute nsIDOMSVGAnimatedString in2; */
    1469               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetIn2(nsIDOMSVGAnimatedString * *aIn)
    1470                 : {
    1471               0 :   return mStringAttributes[IN2].ToDOMAnimatedString(aIn, this);
    1472                 : }
    1473                 : 
    1474                 : 
    1475                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */
    1476               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator)
    1477                 : {
    1478               0 :   return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this);
    1479                 : }
    1480                 : 
    1481                 : /* readonly attribute nsIDOMSVGAnimatedNumber K1; */
    1482               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetK1(nsIDOMSVGAnimatedNumber * *aK1)
    1483                 : {
    1484               0 :   return mNumberAttributes[K1].ToDOMAnimatedNumber(aK1, this);
    1485                 : }
    1486                 : 
    1487                 : /* readonly attribute nsIDOMSVGAnimatedNumber K2; */
    1488               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetK2(nsIDOMSVGAnimatedNumber * *aK2)
    1489                 : {
    1490               0 :   return mNumberAttributes[K2].ToDOMAnimatedNumber(aK2, this);
    1491                 : }
    1492                 : 
    1493                 : /* readonly attribute nsIDOMSVGAnimatedNumber K3; */
    1494               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetK3(nsIDOMSVGAnimatedNumber * *aK3)
    1495                 : {
    1496               0 :   return mNumberAttributes[K3].ToDOMAnimatedNumber(aK3, this);
    1497                 : }
    1498                 : 
    1499                 : /* readonly attribute nsIDOMSVGAnimatedNumber K4; */
    1500               0 : NS_IMETHODIMP nsSVGFECompositeElement::GetK4(nsIDOMSVGAnimatedNumber * *aK4)
    1501                 : {
    1502               0 :   return mNumberAttributes[K4].ToDOMAnimatedNumber(aK4, this);
    1503                 : }
    1504                 : 
    1505                 : NS_IMETHODIMP
    1506               0 : nsSVGFECompositeElement::SetK(float k1, float k2, float k3, float k4)
    1507                 : {
    1508               0 :   NS_ENSURE_FINITE4(k1, k2, k3, k4, NS_ERROR_ILLEGAL_VALUE);
    1509               0 :   mNumberAttributes[K1].SetBaseValue(k1, this);
    1510               0 :   mNumberAttributes[K2].SetBaseValue(k2, this);
    1511               0 :   mNumberAttributes[K3].SetBaseValue(k3, this);
    1512               0 :   mNumberAttributes[K4].SetBaseValue(k4, this);
    1513               0 :   return NS_OK;
    1514                 : }
    1515                 : 
    1516                 : nsresult
    1517               0 : nsSVGFECompositeElement::Filter(nsSVGFilterInstance *instance,
    1518                 :                                 const nsTArray<const Image*>& aSources,
    1519                 :                                 const Image* aTarget,
    1520                 :                                 const nsIntRect& rect)
    1521                 : {
    1522               0 :   PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
    1523                 : 
    1524                 :   // Cairo does not support arithmetic operator
    1525               0 :   if (op == nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC) {
    1526                 :     float k1, k2, k3, k4;
    1527               0 :     GetAnimatedNumberValues(&k1, &k2, &k3, &k4, nsnull);
    1528                 : 
    1529                 :     // Copy the first source image
    1530               0 :     CopyRect(aTarget, aSources[0], rect);
    1531                 : 
    1532               0 :     PRUint8* sourceData = aSources[1]->mImage->Data();
    1533               0 :     PRUint8* targetData = aTarget->mImage->Data();
    1534               0 :     PRUint32 stride = aTarget->mImage->Stride();
    1535                 : 
    1536                 :     // Blend in the second source image
    1537               0 :     float k1Scaled = k1 / 255.0f;
    1538               0 :     float k4Scaled = k4*255.0f;
    1539               0 :     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    1540               0 :       for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    1541               0 :         PRUint32 targIndex = y * stride + 4 * x;
    1542               0 :         for (PRInt32 i = 0; i < 4; i++) {
    1543               0 :           PRUint8 i1 = targetData[targIndex + i];
    1544               0 :           PRUint8 i2 = sourceData[targIndex + i];
    1545               0 :           float result = k1Scaled*i1*i2 + k2*i1 + k3*i2 + k4Scaled;
    1546               0 :           targetData[targIndex + i] =
    1547               0 :                        static_cast<PRUint8>(clamped(result, 0.f, 255.f));
    1548                 :         }
    1549                 :       }
    1550                 :     }
    1551               0 :     return NS_OK;
    1552                 :   }
    1553                 : 
    1554                 :   // Cairo supports the operation we are trying to perform
    1555                 : 
    1556               0 :   gfxContext ctx(aTarget->mImage);
    1557               0 :   ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
    1558               0 :   ctx.SetSource(aSources[1]->mImage);
    1559                 :   // Ensure rendering is limited to the filter primitive subregion
    1560               0 :   ctx.Clip(aTarget->mFilterPrimitiveSubregion);
    1561               0 :   ctx.Paint();
    1562                 : 
    1563               0 :   if (op < SVG_OPERATOR_OVER || op > SVG_OPERATOR_XOR) {
    1564               0 :     return NS_ERROR_FAILURE;
    1565                 :   }
    1566                 :   static const gfxContext::GraphicsOperator opMap[] = {
    1567                 :                                            gfxContext::OPERATOR_DEST,
    1568                 :                                            gfxContext::OPERATOR_OVER,
    1569                 :                                            gfxContext::OPERATOR_IN,
    1570                 :                                            gfxContext::OPERATOR_OUT,
    1571                 :                                            gfxContext::OPERATOR_ATOP,
    1572                 :                                            gfxContext::OPERATOR_XOR };
    1573               0 :   ctx.SetOperator(opMap[op]);
    1574               0 :   ctx.SetSource(aSources[0]->mImage);
    1575               0 :   ctx.Paint();
    1576               0 :   return NS_OK;
    1577                 : }
    1578                 : 
    1579                 : bool
    1580               0 : nsSVGFECompositeElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    1581                 :                                                    nsIAtom* aAttribute) const
    1582                 : {
    1583               0 :   return nsSVGFECompositeElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    1584                 :          (aNameSpaceID == kNameSpaceID_None &&
    1585                 :           (aAttribute == nsGkAtoms::in ||
    1586                 :            aAttribute == nsGkAtoms::in2 ||
    1587                 :            aAttribute == nsGkAtoms::k1 ||
    1588                 :            aAttribute == nsGkAtoms::k2 ||
    1589                 :            aAttribute == nsGkAtoms::k3 ||
    1590                 :            aAttribute == nsGkAtoms::k4 ||
    1591               0 :            aAttribute == nsGkAtoms::_operator));
    1592                 : }
    1593                 : 
    1594                 : void
    1595               0 : nsSVGFECompositeElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    1596                 : {
    1597               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    1598               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
    1599               0 : }
    1600                 : 
    1601                 : nsIntRect
    1602               0 : nsSVGFECompositeElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    1603                 :         const nsSVGFilterInstance& aInstance)
    1604                 : {
    1605               0 :   PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
    1606                 : 
    1607               0 :   if (op == nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC) {
    1608                 :     // "arithmetic" operator can produce non-zero alpha values even where
    1609                 :     // all input alphas are zero, so we can actually render outside the
    1610                 :     // union of the source bboxes.
    1611                 :     // XXX we could also check that k4 is nonzero and check for other
    1612                 :     // cases like k1/k2 or k1/k3 zero.
    1613               0 :     return GetMaxRect();
    1614                 :   }
    1615                 : 
    1616               0 :   if (op == nsSVGFECompositeElement::SVG_OPERATOR_IN ||
    1617                 :       op == nsSVGFECompositeElement::SVG_OPERATOR_ATOP) {
    1618                 :     // We will only draw where in2 has nonzero alpha, so it's a good
    1619                 :     // bounding box for us
    1620               0 :     return aSourceBBoxes[1];
    1621                 :   }
    1622                 : 
    1623                 :   // The regular Porter-Duff operators always compute zero alpha values
    1624                 :   // where all sources have zero alpha, so the union of their bounding
    1625                 :   // boxes is also a bounding box for our rendering
    1626               0 :   return nsSVGFECompositeElementBase::ComputeTargetBBox(aSourceBBoxes, aInstance);
    1627                 : }
    1628                 : 
    1629                 : //----------------------------------------------------------------------
    1630                 : // nsSVGElement methods
    1631                 : 
    1632                 : nsSVGElement::NumberAttributesInfo
    1633               0 : nsSVGFECompositeElement::GetNumberInfo()
    1634                 : {
    1635                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    1636               0 :                               ArrayLength(sNumberInfo));
    1637                 : }
    1638                 : 
    1639                 : nsSVGElement::EnumAttributesInfo
    1640               0 : nsSVGFECompositeElement::GetEnumInfo()
    1641                 : {
    1642                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    1643               0 :                             ArrayLength(sEnumInfo));
    1644                 : }
    1645                 : 
    1646                 : nsSVGElement::StringAttributesInfo
    1647               0 : nsSVGFECompositeElement::GetStringInfo()
    1648                 : {
    1649                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    1650               0 :                               ArrayLength(sStringInfo));
    1651                 : }
    1652                 : 
    1653                 : //---------------------Component Transfer------------------------
    1654                 : 
    1655                 : typedef nsSVGFE nsSVGFEComponentTransferElementBase;
    1656                 : 
    1657                 : class nsSVGFEComponentTransferElement : public nsSVGFEComponentTransferElementBase,
    1658                 :                                         public nsIDOMSVGFEComponentTransferElement
    1659               0 : {
    1660                 :   friend nsresult NS_NewSVGFEComponentTransferElement(nsIContent **aResult,
    1661                 :                                                       already_AddRefed<nsINodeInfo> aNodeInfo);
    1662                 : protected:
    1663               0 :   nsSVGFEComponentTransferElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    1664               0 :     : nsSVGFEComponentTransferElementBase(aNodeInfo) {}
    1665                 : 
    1666                 : public:
    1667                 :   // interfaces:
    1668                 :   NS_DECL_ISUPPORTS_INHERITED
    1669                 : 
    1670                 :   // FE Base
    1671               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEComponentTransferElementBase::)
    1672                 : 
    1673                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    1674                 :                           const nsTArray<const Image*>& aSources,
    1675                 :                           const Image* aTarget,
    1676                 :                           const nsIntRect& aDataRect);
    1677                 :   virtual bool AttributeAffectsRendering(
    1678                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    1679               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    1680                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    1681                 : 
    1682                 :   // Component Transfer
    1683                 :   NS_DECL_NSIDOMSVGFECOMPONENTTRANSFERELEMENT
    1684                 : 
    1685               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEComponentTransferElementBase::)
    1686                 : 
    1687               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEComponentTransferElementBase::)
    1688               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEComponentTransferElementBase::)
    1689                 : 
    1690                 :   // nsIContent
    1691                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    1692                 : 
    1693                 :   virtual nsXPCClassInfo* GetClassInfo();
    1694                 : protected:
    1695               0 :   virtual bool OperatesOnPremultipledAlpha(PRInt32) { return false; }
    1696                 : 
    1697                 :   virtual StringAttributesInfo GetStringInfo();
    1698                 : 
    1699                 :   enum { RESULT, IN1 };
    1700                 :   nsSVGString mStringAttributes[2];
    1701                 :   static StringInfo sStringInfo[2];
    1702                 : };
    1703                 : 
    1704                 : nsSVGElement::StringInfo nsSVGFEComponentTransferElement::sStringInfo[2] =
    1705                 : {
    1706                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    1707                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    1708                 : };
    1709                 : 
    1710               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEComponentTransfer)
    1711                 : 
    1712                 : //----------------------------------------------------------------------
    1713                 : // nsISupports methods
    1714                 : 
    1715               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEComponentTransferElement,nsSVGFEComponentTransferElementBase)
    1716               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEComponentTransferElement,nsSVGFEComponentTransferElementBase)
    1717                 : 
    1718               0 : DOMCI_NODE_DATA(SVGFEComponentTransferElement, nsSVGFEComponentTransferElement)
    1719                 : 
    1720               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEComponentTransferElement)
    1721               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEComponentTransferElement, nsIDOMNode,
    1722                 :                            nsIDOMElement, nsIDOMSVGElement,
    1723                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    1724                 :                            nsIDOMSVGFEComponentTransferElement)
    1725               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEComponentTransferElement)
    1726               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEComponentTransferElementBase)
    1727                 : 
    1728                 : //----------------------------------------------------------------------
    1729                 : // nsIDOMNode methods
    1730                 : 
    1731               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEComponentTransferElement)
    1732                 : 
    1733                 : //----------------------------------------------------------------------
    1734                 : // nsIDOMSVGFEComponentTransferElement methods
    1735                 : 
    1736                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    1737                 : NS_IMETHODIMP
    1738               0 : nsSVGFEComponentTransferElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    1739                 : {
    1740               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    1741                 : }
    1742                 : 
    1743                 : //----------------------------------------------------------------------
    1744                 : // nsSVGElement methods
    1745                 : 
    1746                 : nsSVGElement::StringAttributesInfo
    1747               0 : nsSVGFEComponentTransferElement::GetStringInfo()
    1748                 : {
    1749                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    1750               0 :                               ArrayLength(sStringInfo));
    1751                 : }
    1752                 : 
    1753                 : //--------------------------------------------
    1754                 : 
    1755                 : #define NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID \
    1756                 :     { 0xafab106d, 0xbc18, 0x4f7f, \
    1757                 :   { 0x9e, 0x29, 0xfe, 0xb4, 0xb0, 0x16, 0x5f, 0xf4 } }
    1758                 : 
    1759                 : typedef SVGFEUnstyledElement nsSVGComponentTransferFunctionElementBase;
    1760                 : 
    1761                 : class nsSVGComponentTransferFunctionElement : public nsSVGComponentTransferFunctionElementBase
    1762               0 : {
    1763                 :   friend nsresult NS_NewSVGComponentTransferFunctionElement(nsIContent **aResult,
    1764                 :                                                             already_AddRefed<nsINodeInfo> aNodeInfo);
    1765                 : protected:
    1766               0 :   nsSVGComponentTransferFunctionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    1767               0 :     : nsSVGComponentTransferFunctionElementBase(aNodeInfo) {}
    1768                 : 
    1769                 : public:
    1770                 :   // interfaces:
    1771                 :   NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID)
    1772                 : 
    1773                 :   NS_DECL_ISUPPORTS_INHERITED
    1774                 :   NS_DECL_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT
    1775                 : 
    1776                 :   virtual bool AttributeAffectsRendering(
    1777                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    1778                 : 
    1779                 :   virtual PRInt32 GetChannel() = 0;
    1780                 :   void GenerateLookupTable(PRUint8* aTable);
    1781                 : 
    1782                 : protected:
    1783                 :   virtual NumberAttributesInfo GetNumberInfo();
    1784                 :   virtual EnumAttributesInfo GetEnumInfo();
    1785                 :   virtual NumberListAttributesInfo GetNumberListInfo();
    1786                 : 
    1787                 :   // nsIDOMSVGComponentTransferFunctionElement properties:
    1788                 :   enum { TABLEVALUES };
    1789                 :   SVGAnimatedNumberList mNumberListAttributes[1];
    1790                 :   static NumberListInfo sNumberListInfo[1];
    1791                 : 
    1792                 :   enum { SLOPE, INTERCEPT, AMPLITUDE, EXPONENT, OFFSET };
    1793                 :   nsSVGNumber2 mNumberAttributes[5];
    1794                 :   static NumberInfo sNumberInfo[5];
    1795                 : 
    1796                 :   enum { TYPE };
    1797                 :   nsSVGEnum mEnumAttributes[1];
    1798                 :   static nsSVGEnumMapping sTypeMap[];
    1799                 :   static EnumInfo sEnumInfo[1];
    1800                 : };
    1801                 : 
    1802                 : nsresult
    1803               0 : nsSVGFEComponentTransferElement::Filter(nsSVGFilterInstance *instance,
    1804                 :                                         const nsTArray<const Image*>& aSources,
    1805                 :                                         const Image* aTarget,
    1806                 :                                         const nsIntRect& rect)
    1807                 : {
    1808               0 :   PRUint8* sourceData = aSources[0]->mImage->Data();
    1809               0 :   PRUint8* targetData = aTarget->mImage->Data();
    1810               0 :   PRUint32 stride = aTarget->mImage->Stride();
    1811                 : 
    1812                 :   PRUint8 tableR[256], tableG[256], tableB[256], tableA[256];
    1813               0 :   for (int i=0; i<256; i++)
    1814               0 :     tableR[i] = tableG[i] = tableB[i] = tableA[i] = i;
    1815               0 :   PRUint8* tables[] = { tableR, tableG, tableB, tableA };
    1816               0 :   for (nsIContent* childContent = nsINode::GetFirstChild();
    1817                 :        childContent;
    1818               0 :        childContent = childContent->GetNextSibling()) {
    1819                 : 
    1820               0 :     nsRefPtr<nsSVGComponentTransferFunctionElement> child;
    1821                 :     CallQueryInterface(childContent,
    1822               0 :             (nsSVGComponentTransferFunctionElement**)getter_AddRefs(child));
    1823               0 :     if (child) {
    1824               0 :       child->GenerateLookupTable(tables[child->GetChannel()]);
    1825                 :     }
    1826                 :   }
    1827                 : 
    1828               0 :   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    1829               0 :     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    1830               0 :       PRInt32 targIndex = y * stride + x * 4;
    1831               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_B] =
    1832               0 :         tableB[sourceData[targIndex + GFX_ARGB32_OFFSET_B]];
    1833               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_G] =
    1834               0 :         tableG[sourceData[targIndex + GFX_ARGB32_OFFSET_G]];
    1835               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_R] =
    1836               0 :         tableR[sourceData[targIndex + GFX_ARGB32_OFFSET_R]];
    1837               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_A] =
    1838               0 :         tableA[sourceData[targIndex + GFX_ARGB32_OFFSET_A]];
    1839                 :     }
    1840                 :   }
    1841               0 :   return NS_OK;
    1842                 : }
    1843                 : 
    1844                 : bool
    1845               0 : nsSVGFEComponentTransferElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    1846                 :                                                            nsIAtom* aAttribute) const
    1847                 : {
    1848               0 :   return nsSVGFEComponentTransferElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    1849                 :          (aNameSpaceID == kNameSpaceID_None &&
    1850               0 :           aAttribute == nsGkAtoms::in);
    1851                 : }
    1852                 : 
    1853                 : void
    1854               0 : nsSVGFEComponentTransferElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    1855                 : {
    1856               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    1857               0 : }
    1858                 : 
    1859                 : nsSVGElement::NumberListInfo nsSVGComponentTransferFunctionElement::sNumberListInfo[1] =
    1860                 : {
    1861                 :   { &nsGkAtoms::tableValues }
    1862                 : };
    1863                 : 
    1864                 : nsSVGElement::NumberInfo nsSVGComponentTransferFunctionElement::sNumberInfo[5] =
    1865                 : {
    1866                 :   { &nsGkAtoms::slope,     1, false },
    1867                 :   { &nsGkAtoms::intercept, 0, false },
    1868                 :   { &nsGkAtoms::amplitude, 1, false },
    1869                 :   { &nsGkAtoms::exponent,  1, false },
    1870                 :   { &nsGkAtoms::offset,    0, false }
    1871                 : };
    1872                 : 
    1873                 : nsSVGEnumMapping nsSVGComponentTransferFunctionElement::sTypeMap[] = {
    1874                 :   {&nsGkAtoms::identity,
    1875                 :    nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY},
    1876                 :   {&nsGkAtoms::table,
    1877                 :    nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_TABLE},
    1878                 :   {&nsGkAtoms::discrete,
    1879                 :    nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE},
    1880                 :   {&nsGkAtoms::linear,
    1881                 :    nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_LINEAR},
    1882                 :   {&nsGkAtoms::gamma,
    1883                 :    nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_GAMMA},
    1884                 :   {nsnull, 0}
    1885                 : };
    1886                 : 
    1887                 : nsSVGElement::EnumInfo nsSVGComponentTransferFunctionElement::sEnumInfo[1] =
    1888                 : {
    1889                 :   { &nsGkAtoms::type,
    1890                 :     sTypeMap,
    1891                 :     nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY
    1892                 :   }
    1893                 : };
    1894                 : 
    1895                 : //----------------------------------------------------------------------
    1896                 : // nsISupports methods
    1897                 : 
    1898               0 : NS_IMPL_ADDREF_INHERITED(nsSVGComponentTransferFunctionElement,nsSVGComponentTransferFunctionElementBase)
    1899               0 : NS_IMPL_RELEASE_INHERITED(nsSVGComponentTransferFunctionElement,nsSVGComponentTransferFunctionElementBase)
    1900                 : 
    1901                 : NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGComponentTransferFunctionElement, NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID)
    1902                 : 
    1903               0 : NS_INTERFACE_MAP_BEGIN(nsSVGComponentTransferFunctionElement)
    1904                 :    // nsISupports is an ambiguous base of nsSVGFE so we have to work
    1905                 :    // around that
    1906               0 :    if ( aIID.Equals(NS_GET_IID(nsSVGComponentTransferFunctionElement)) )
    1907               0 :      foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
    1908                 :    else
    1909               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElementBase)
    1910                 : 
    1911                 : 
    1912                 : //----------------------------------------------------------------------
    1913                 : // nsFEUnstyledElement methods
    1914                 : 
    1915                 : bool
    1916               0 : nsSVGComponentTransferFunctionElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    1917                 :                                                                  nsIAtom* aAttribute) const
    1918                 : {
    1919                 :   return aNameSpaceID == kNameSpaceID_None &&
    1920                 :          (aAttribute == nsGkAtoms::tableValues ||
    1921                 :           aAttribute == nsGkAtoms::slope ||
    1922                 :           aAttribute == nsGkAtoms::intercept ||
    1923                 :           aAttribute == nsGkAtoms::amplitude ||
    1924                 :           aAttribute == nsGkAtoms::exponent ||
    1925                 :           aAttribute == nsGkAtoms::offset ||
    1926               0 :           aAttribute == nsGkAtoms::type);
    1927                 : }
    1928                 : 
    1929                 : //----------------------------------------------------------------------
    1930                 : // nsIDOMSVGComponentTransferFunctionElement methods
    1931                 : 
    1932                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
    1933               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
    1934                 : {
    1935               0 :   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
    1936                 : }
    1937                 : 
    1938                 : /* readonly attribute nsIDOMSVGAnimatedNumberList tableValues; */
    1939               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetTableValues(nsIDOMSVGAnimatedNumberList * *aTableValues)
    1940                 : {
    1941                 :   *aTableValues = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[TABLEVALUES],
    1942               0 :                                                           this, TABLEVALUES).get();
    1943               0 :   return NS_OK;
    1944                 : }
    1945                 : 
    1946                 : /* readonly attribute nsIDOMSVGAnimatedNumber slope; */
    1947               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetSlope(nsIDOMSVGAnimatedNumber * *aSlope)
    1948                 : {
    1949               0 :   return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(aSlope, this);
    1950                 : }
    1951                 : 
    1952                 : /* readonly attribute nsIDOMSVGAnimatedNumber intercept; */
    1953               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetIntercept(nsIDOMSVGAnimatedNumber * *aIntercept)
    1954                 : {
    1955               0 :   return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(aIntercept, this);
    1956                 : }
    1957                 : 
    1958                 : /* readonly attribute nsIDOMSVGAnimatedNumber amplitude; */
    1959               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetAmplitude(nsIDOMSVGAnimatedNumber * *aAmplitude)
    1960                 : {
    1961               0 :   return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(aAmplitude, this);
    1962                 : }
    1963                 : 
    1964                 : /* readonly attribute nsIDOMSVGAnimatedNumber exponent; */
    1965               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetExponent(nsIDOMSVGAnimatedNumber * *aExponent)
    1966                 : {
    1967               0 :   return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(aExponent, this);
    1968                 : }
    1969                 : 
    1970                 : /* readonly attribute nsIDOMSVGAnimatedNumber offset; */
    1971               0 : NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetOffset(nsIDOMSVGAnimatedNumber * *aOffset)
    1972                 : {
    1973               0 :   return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(aOffset, this);
    1974                 : }
    1975                 : 
    1976                 : void
    1977               0 : nsSVGComponentTransferFunctionElement::GenerateLookupTable(PRUint8 *aTable)
    1978                 : {
    1979               0 :   PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
    1980                 : 
    1981                 :   float slope, intercept, amplitude, exponent, offset;
    1982                 :   GetAnimatedNumberValues(&slope, &intercept, &amplitude, 
    1983               0 :                           &exponent, &offset, nsnull);
    1984                 : 
    1985                 :   const SVGNumberList &tableValues =
    1986               0 :     mNumberListAttributes[TABLEVALUES].GetAnimValue();
    1987               0 :   PRUint32 tvLength = tableValues.Length();
    1988                 : 
    1989                 :   PRUint32 i;
    1990                 : 
    1991               0 :   switch (type) {
    1992                 :   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_TABLE:
    1993                 :   {
    1994               0 :     if (tableValues.Length() <= 1)
    1995               0 :       break;
    1996                 : 
    1997               0 :     for (i = 0; i < 256; i++) {
    1998               0 :       PRUint32 k = (i * (tvLength - 1)) / 255;
    1999               0 :       float v1 = tableValues[k];
    2000               0 :       float v2 = tableValues[NS_MIN(k + 1, tvLength - 1)];
    2001                 :       PRInt32 val =
    2002               0 :         PRInt32(255 * (v1 + (i/255.0f - k/float(tvLength-1))*(tvLength - 1)*(v2 - v1)));
    2003               0 :       val = NS_MIN(255, val);
    2004               0 :       val = NS_MAX(0, val);
    2005               0 :       aTable[i] = val;
    2006                 :     }
    2007               0 :     break;
    2008                 :   }
    2009                 : 
    2010                 :   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE:
    2011                 :   {
    2012               0 :     if (tableValues.Length() <= 1)
    2013               0 :       break;
    2014                 : 
    2015               0 :     for (i = 0; i < 256; i++) {
    2016               0 :       PRUint32 k = (i * tvLength) / 255;
    2017               0 :       k = NS_MIN(k, tvLength - 1);
    2018               0 :       float v = tableValues[k];
    2019               0 :       PRInt32 val = PRInt32(255 * v);
    2020               0 :       val = NS_MIN(255, val);
    2021               0 :       val = NS_MAX(0, val);
    2022               0 :       aTable[i] = val;
    2023                 :     }
    2024               0 :     break;
    2025                 :   }
    2026                 : 
    2027                 :   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_LINEAR:
    2028                 :   {
    2029               0 :     for (i = 0; i < 256; i++) {
    2030               0 :       PRInt32 val = PRInt32(slope * i + 255 * intercept);
    2031               0 :       val = NS_MIN(255, val);
    2032               0 :       val = NS_MAX(0, val);
    2033               0 :       aTable[i] = val;
    2034                 :     }
    2035               0 :     break;
    2036                 :   }
    2037                 : 
    2038                 :   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_GAMMA:
    2039                 :   {
    2040               0 :     for (i = 0; i < 256; i++) {
    2041               0 :       PRInt32 val = PRInt32(255 * (amplitude * pow(i / 255.0f, exponent) + offset));
    2042               0 :       val = NS_MIN(255, val);
    2043               0 :       val = NS_MAX(0, val);
    2044               0 :       aTable[i] = val;
    2045                 :     }
    2046               0 :     break;
    2047                 :   }
    2048                 : 
    2049                 :   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY:
    2050                 :   default:
    2051               0 :     break;
    2052                 :   }
    2053               0 : }
    2054                 : 
    2055                 : //----------------------------------------------------------------------
    2056                 : // nsSVGElement methods
    2057                 : 
    2058                 : nsSVGElement::NumberListAttributesInfo
    2059               0 : nsSVGComponentTransferFunctionElement::GetNumberListInfo()
    2060                 : {
    2061                 :   return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
    2062               0 :                                   ArrayLength(sNumberListInfo));
    2063                 : }
    2064                 : 
    2065                 : nsSVGElement::EnumAttributesInfo
    2066               0 : nsSVGComponentTransferFunctionElement::GetEnumInfo()
    2067                 : {
    2068                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    2069               0 :                             ArrayLength(sEnumInfo));
    2070                 : }
    2071                 : 
    2072                 : nsSVGElement::NumberAttributesInfo
    2073               0 : nsSVGComponentTransferFunctionElement::GetNumberInfo()
    2074                 : {
    2075                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    2076               0 :                               ArrayLength(sNumberInfo));
    2077                 : }
    2078                 : 
    2079                 : class nsSVGFEFuncRElement : public nsSVGComponentTransferFunctionElement,
    2080                 :                             public nsIDOMSVGFEFuncRElement
    2081               0 : {
    2082                 :   friend nsresult NS_NewSVGFEFuncRElement(nsIContent **aResult,
    2083                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2084                 : protected:
    2085               0 :   nsSVGFEFuncRElement(already_AddRefed<nsINodeInfo> aNodeInfo) 
    2086               0 :     : nsSVGComponentTransferFunctionElement(aNodeInfo) {}
    2087                 : 
    2088                 : public:
    2089                 :   // interfaces:
    2090                 :   NS_DECL_ISUPPORTS_INHERITED
    2091                 : 
    2092               0 :   NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::)
    2093                 : 
    2094                 :   NS_DECL_NSIDOMSVGFEFUNCRELEMENT
    2095                 : 
    2096               0 :   virtual PRInt32 GetChannel() { return 0; }
    2097                 :   
    2098               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::)
    2099               0 :   NS_FORWARD_NSIDOMNODE(nsSVGComponentTransferFunctionElement::)
    2100               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::)
    2101                 : 
    2102                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2103                 : 
    2104                 :   virtual nsXPCClassInfo* GetClassInfo();
    2105                 : };
    2106                 : 
    2107               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncRElement,nsSVGComponentTransferFunctionElement)
    2108               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncRElement,nsSVGComponentTransferFunctionElement)
    2109                 : 
    2110               0 : DOMCI_NODE_DATA(SVGFEFuncRElement, nsSVGFEFuncRElement)
    2111                 : 
    2112               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEFuncRElement)
    2113               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEFuncRElement, nsIDOMNode, nsIDOMElement,
    2114                 :                            nsIDOMSVGElement,
    2115                 :                            nsIDOMSVGComponentTransferFunctionElement,
    2116                 :                            nsIDOMSVGFEFuncRElement)
    2117               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEFuncRElement)
    2118               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement)
    2119                 : 
    2120               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncR)
    2121               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFuncRElement)
    2122                 : 
    2123                 : 
    2124                 : class nsSVGFEFuncGElement : public nsSVGComponentTransferFunctionElement,
    2125                 :                             public nsIDOMSVGFEFuncGElement
    2126               0 : {
    2127                 :   friend nsresult NS_NewSVGFEFuncGElement(nsIContent **aResult,
    2128                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2129                 : protected:
    2130               0 :   nsSVGFEFuncGElement(already_AddRefed<nsINodeInfo> aNodeInfo) 
    2131               0 :     : nsSVGComponentTransferFunctionElement(aNodeInfo) {}
    2132                 : 
    2133                 : public:
    2134                 :   // interfaces:
    2135                 :   NS_DECL_ISUPPORTS_INHERITED
    2136                 : 
    2137               0 :   NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::)
    2138                 : 
    2139                 :   NS_DECL_NSIDOMSVGFEFUNCGELEMENT
    2140                 : 
    2141               0 :   virtual PRInt32 GetChannel() { return 1; }
    2142                 : 
    2143               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::)
    2144               0 :   NS_FORWARD_NSIDOMNODE(nsSVGComponentTransferFunctionElement::)
    2145               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::)
    2146                 : 
    2147                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2148                 : 
    2149                 :   virtual nsXPCClassInfo* GetClassInfo();
    2150                 : };
    2151                 : 
    2152               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncGElement,nsSVGComponentTransferFunctionElement)
    2153               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncGElement,nsSVGComponentTransferFunctionElement)
    2154                 : 
    2155               0 : DOMCI_NODE_DATA(SVGFEFuncGElement, nsSVGFEFuncGElement)
    2156                 : 
    2157               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEFuncGElement)
    2158               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEFuncGElement, nsIDOMNode, nsIDOMElement,
    2159                 :                            nsIDOMSVGElement,
    2160                 :                            nsIDOMSVGComponentTransferFunctionElement,
    2161                 :                            nsIDOMSVGFEFuncGElement)
    2162               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEFuncGElement)
    2163               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement)
    2164                 : 
    2165               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncG)
    2166               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFuncGElement)
    2167                 : 
    2168                 : 
    2169                 : class nsSVGFEFuncBElement : public nsSVGComponentTransferFunctionElement,
    2170                 :                             public nsIDOMSVGFEFuncBElement
    2171               0 : {
    2172                 :   friend nsresult NS_NewSVGFEFuncBElement(nsIContent **aResult,
    2173                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2174                 : protected:
    2175               0 :   nsSVGFEFuncBElement(already_AddRefed<nsINodeInfo> aNodeInfo) 
    2176               0 :     : nsSVGComponentTransferFunctionElement(aNodeInfo) {}
    2177                 : 
    2178                 : public:
    2179                 :   // interfaces:
    2180                 :   NS_DECL_ISUPPORTS_INHERITED
    2181                 : 
    2182               0 :   NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::)
    2183                 : 
    2184                 :   NS_DECL_NSIDOMSVGFEFUNCBELEMENT
    2185                 : 
    2186               0 :   virtual PRInt32 GetChannel() { return 2; }
    2187                 : 
    2188               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::)
    2189               0 :   NS_FORWARD_NSIDOMNODE(nsSVGComponentTransferFunctionElement::)
    2190               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::)
    2191                 : 
    2192                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2193                 : 
    2194                 :   virtual nsXPCClassInfo* GetClassInfo();
    2195                 : };
    2196                 : 
    2197               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncBElement,nsSVGComponentTransferFunctionElement)
    2198               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncBElement,nsSVGComponentTransferFunctionElement)
    2199                 : 
    2200               0 : DOMCI_NODE_DATA(SVGFEFuncBElement, nsSVGFEFuncBElement)
    2201                 : 
    2202               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEFuncBElement)
    2203               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEFuncBElement, nsIDOMNode, nsIDOMElement,
    2204                 :                            nsIDOMSVGElement,
    2205                 :                            nsIDOMSVGComponentTransferFunctionElement,
    2206                 :                            nsIDOMSVGFEFuncBElement)
    2207               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEFuncBElement)
    2208               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement)
    2209                 : 
    2210               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncB)
    2211               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFuncBElement)
    2212                 : 
    2213                 : 
    2214                 : class nsSVGFEFuncAElement : public nsSVGComponentTransferFunctionElement,
    2215                 :                             public nsIDOMSVGFEFuncAElement
    2216               0 : {
    2217                 :   friend nsresult NS_NewSVGFEFuncAElement(nsIContent **aResult,
    2218                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2219                 : protected:
    2220               0 :   nsSVGFEFuncAElement(already_AddRefed<nsINodeInfo> aNodeInfo) 
    2221               0 :     : nsSVGComponentTransferFunctionElement(aNodeInfo) {}
    2222                 : 
    2223                 : public:
    2224                 :   // interfaces:
    2225                 :   NS_DECL_ISUPPORTS_INHERITED
    2226                 : 
    2227               0 :   NS_FORWARD_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT(nsSVGComponentTransferFunctionElement::)
    2228                 : 
    2229                 :   NS_DECL_NSIDOMSVGFEFUNCAELEMENT
    2230                 : 
    2231               0 :   virtual PRInt32 GetChannel() { return 3; }
    2232                 : 
    2233               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGComponentTransferFunctionElement::)
    2234               0 :   NS_FORWARD_NSIDOMNODE(nsSVGComponentTransferFunctionElement::)
    2235               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGComponentTransferFunctionElement::)
    2236                 : 
    2237                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2238                 : 
    2239                 :   virtual nsXPCClassInfo* GetClassInfo();
    2240                 : };
    2241                 : 
    2242               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEFuncAElement,nsSVGComponentTransferFunctionElement)
    2243               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEFuncAElement,nsSVGComponentTransferFunctionElement)
    2244                 : 
    2245               0 : DOMCI_NODE_DATA(SVGFEFuncAElement, nsSVGFEFuncAElement)
    2246                 : 
    2247               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEFuncAElement)
    2248               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEFuncAElement, nsIDOMNode, nsIDOMElement,
    2249                 :                            nsIDOMSVGElement,
    2250                 :                            nsIDOMSVGComponentTransferFunctionElement,
    2251                 :                            nsIDOMSVGFEFuncAElement)
    2252               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEFuncAElement)
    2253               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElement)
    2254                 : 
    2255               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEFuncA)
    2256               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFuncAElement)
    2257                 : 
    2258                 : //---------------------Merge------------------------
    2259                 : 
    2260                 : typedef nsSVGFE nsSVGFEMergeElementBase;
    2261                 : 
    2262                 : class nsSVGFEMergeElement : public nsSVGFEMergeElementBase,
    2263                 :                             public nsIDOMSVGFEMergeElement
    2264               0 : {
    2265                 :   friend nsresult NS_NewSVGFEMergeElement(nsIContent **aResult,
    2266                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2267                 : protected:
    2268               0 :   nsSVGFEMergeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2269               0 :     : nsSVGFEMergeElementBase(aNodeInfo) {}
    2270                 : 
    2271                 : public:
    2272                 :   // interfaces:
    2273                 :   NS_DECL_ISUPPORTS_INHERITED
    2274                 : 
    2275                 :   // FE Base
    2276               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMergeElementBase::)
    2277                 : 
    2278                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    2279                 :                           const nsTArray<const Image*>& aSources,
    2280                 :                           const Image* aTarget,
    2281                 :                           const nsIntRect& aDataRect);
    2282               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    2283                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    2284                 : 
    2285                 :   // Merge
    2286                 :   NS_DECL_NSIDOMSVGFEMERGEELEMENT
    2287                 : 
    2288               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeElementBase::)
    2289                 : 
    2290               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEMergeElementBase::)
    2291               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEMergeElementBase::)
    2292                 : 
    2293                 :   // nsIContent
    2294                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2295                 : 
    2296                 :   virtual nsXPCClassInfo* GetClassInfo();
    2297                 : protected:
    2298                 :   virtual StringAttributesInfo GetStringInfo();
    2299                 : 
    2300                 :   enum { RESULT };
    2301                 :   nsSVGString mStringAttributes[1];
    2302                 :   static StringInfo sStringInfo[1];
    2303                 : };
    2304                 : 
    2305                 : typedef SVGFEUnstyledElement nsSVGFEMergeNodeElementBase;
    2306                 : 
    2307                 : #define NS_SVG_FE_MERGE_NODE_CID \
    2308                 :     { 0x413687ec, 0x77fd, 0x4077, \
    2309                 :   { 0x9d, 0x7a, 0x97, 0x51, 0xa8, 0x4b, 0x7b, 0x40 } }
    2310                 : 
    2311                 : class nsSVGFEMergeNodeElement : public nsSVGFEMergeNodeElementBase,
    2312                 :                                 public nsIDOMSVGFEMergeNodeElement
    2313               0 : {
    2314                 :   friend nsresult NS_NewSVGFEMergeNodeElement(nsIContent **aResult,
    2315                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2316                 : protected:
    2317               0 :   nsSVGFEMergeNodeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2318               0 :     : nsSVGFEMergeNodeElementBase(aNodeInfo) {}
    2319                 : 
    2320                 : public:
    2321                 :   NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_MERGE_NODE_CID)
    2322                 : 
    2323                 :   // interfaces:
    2324                 :   NS_DECL_ISUPPORTS_INHERITED
    2325                 : 
    2326                 :   NS_DECL_NSIDOMSVGFEMERGENODEELEMENT
    2327                 : 
    2328               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeNodeElementBase::)
    2329                 : 
    2330               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEMergeNodeElementBase::)
    2331               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEMergeNodeElementBase::)
    2332                 : 
    2333                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2334                 : 
    2335                 :   virtual bool AttributeAffectsRendering(
    2336                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    2337                 : 
    2338               0 :   const nsSVGString* In1() { return &mStringAttributes[IN1]; }
    2339                 :   
    2340                 :   operator nsISupports*() { return static_cast<nsIContent*>(this); }
    2341                 : 
    2342                 :   virtual nsXPCClassInfo* GetClassInfo();
    2343                 : protected:
    2344                 :   virtual StringAttributesInfo GetStringInfo();
    2345                 : 
    2346                 :   enum { IN1 };
    2347                 :   nsSVGString mStringAttributes[1];
    2348                 :   static StringInfo sStringInfo[1];
    2349                 : };
    2350                 : 
    2351                 : nsSVGElement::StringInfo nsSVGFEMergeElement::sStringInfo[1] =
    2352                 : {
    2353                 :   { &nsGkAtoms::result, kNameSpaceID_None, true }
    2354                 : };
    2355                 : 
    2356               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEMerge)
    2357                 : 
    2358                 : //----------------------------------------------------------------------
    2359                 : // nsISupports methods
    2360                 : 
    2361               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEMergeElement,nsSVGFEMergeElementBase)
    2362               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEMergeElement,nsSVGFEMergeElementBase)
    2363                 : 
    2364               0 : DOMCI_NODE_DATA(SVGFEMergeElement, nsSVGFEMergeElement)
    2365                 : 
    2366               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEMergeElement)
    2367               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEMergeElement, nsIDOMNode, nsIDOMElement,
    2368                 :                            nsIDOMSVGElement,
    2369                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    2370                 :                            nsIDOMSVGFEMergeElement)
    2371               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMergeElement)
    2372               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeElementBase)
    2373                 : 
    2374                 : //----------------------------------------------------------------------
    2375                 : // nsIDOMNode methods
    2376                 : 
    2377               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMergeElement)
    2378                 : 
    2379                 : nsresult
    2380               0 : nsSVGFEMergeElement::Filter(nsSVGFilterInstance *instance,
    2381                 :                             const nsTArray<const Image*>& aSources,
    2382                 :                             const Image* aTarget,
    2383                 :                             const nsIntRect& rect)
    2384                 : {
    2385               0 :   gfxContext ctx(aTarget->mImage);
    2386               0 :   ctx.Clip(aTarget->mFilterPrimitiveSubregion);
    2387                 : 
    2388               0 :   for (PRUint32 i = 0; i < aSources.Length(); i++) {
    2389               0 :     ctx.SetSource(aSources[i]->mImage);
    2390               0 :     ctx.Paint();
    2391                 :   }
    2392               0 :   return NS_OK;
    2393                 : }
    2394                 : 
    2395                 : void
    2396               0 : nsSVGFEMergeElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    2397                 : {
    2398               0 :   for (nsIContent* child = nsINode::GetFirstChild();
    2399                 :        child;
    2400               0 :        child = child->GetNextSibling()) {
    2401               0 :     nsRefPtr<nsSVGFEMergeNodeElement> node;
    2402               0 :     CallQueryInterface(child, (nsSVGFEMergeNodeElement**)getter_AddRefs(node));
    2403               0 :     if (node) {
    2404               0 :       aSources.AppendElement(nsSVGStringInfo(node->In1(), node));
    2405                 :     }
    2406                 :   }
    2407               0 : }
    2408                 : 
    2409                 : //----------------------------------------------------------------------
    2410                 : // nsSVGElement methods
    2411                 : 
    2412                 : nsSVGElement::StringAttributesInfo
    2413               0 : nsSVGFEMergeElement::GetStringInfo()
    2414                 : {
    2415                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    2416               0 :                               ArrayLength(sStringInfo));
    2417                 : }
    2418                 : 
    2419                 : //---------------------Merge Node------------------------
    2420                 : 
    2421                 : NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFEMergeNodeElement, NS_SVG_FE_MERGE_NODE_CID)
    2422                 : 
    2423                 : nsSVGElement::StringInfo nsSVGFEMergeNodeElement::sStringInfo[1] =
    2424                 : {
    2425                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    2426                 : };
    2427                 : 
    2428               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEMergeNode)
    2429                 : 
    2430                 : //----------------------------------------------------------------------
    2431                 : // nsISupports methods
    2432                 : 
    2433               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEMergeNodeElement,nsSVGFEMergeNodeElementBase)
    2434               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEMergeNodeElement,nsSVGFEMergeNodeElementBase)
    2435                 : 
    2436               0 : DOMCI_NODE_DATA(SVGFEMergeNodeElement, nsSVGFEMergeNodeElement)
    2437                 : 
    2438               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEMergeNodeElement)
    2439               0 :   NS_NODE_INTERFACE_TABLE4(nsSVGFEMergeNodeElement, nsIDOMNode, nsIDOMElement,
    2440                 :                            nsIDOMSVGElement, nsIDOMSVGFEMergeNodeElement)
    2441                 :    // nsISupports is an ambiguous base of nsSVGFE so we have to work
    2442                 :    // around that
    2443               0 :    if ( aIID.Equals(NS_GET_IID(nsSVGFEMergeNodeElement)) )
    2444               0 :      foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
    2445                 :    else
    2446               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMergeNodeElement)
    2447               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeNodeElementBase)
    2448                 : 
    2449                 : //----------------------------------------------------------------------
    2450                 : // nsIDOMNode methods
    2451                 : 
    2452               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMergeNodeElement)
    2453                 : 
    2454                 : //----------------------------------------------------------------------
    2455                 : // nsFEUnstyledElement methods
    2456                 : 
    2457                 : bool
    2458               0 : nsSVGFEMergeNodeElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    2459                 :                                                    nsIAtom* aAttribute) const
    2460                 : {
    2461               0 :   return aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::in;
    2462                 : }
    2463                 : 
    2464                 : //----------------------------------------------------------------------
    2465                 : // nsIDOMSVGFEMergeNodeElement methods
    2466                 : 
    2467                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    2468               0 : NS_IMETHODIMP nsSVGFEMergeNodeElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    2469                 : {
    2470               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    2471                 : }
    2472                 : 
    2473                 : //----------------------------------------------------------------------
    2474                 : // nsSVGElement methods
    2475                 : 
    2476                 : nsSVGElement::StringAttributesInfo
    2477               0 : nsSVGFEMergeNodeElement::GetStringInfo()
    2478                 : {
    2479                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    2480               0 :                               ArrayLength(sStringInfo));
    2481                 : }
    2482                 : 
    2483                 : //---------------------Offset------------------------
    2484                 : 
    2485                 : typedef nsSVGFE nsSVGFEOffsetElementBase;
    2486                 : 
    2487                 : class nsSVGFEOffsetElement : public nsSVGFEOffsetElementBase,
    2488                 :                              public nsIDOMSVGFEOffsetElement
    2489               0 : {
    2490                 :   friend nsresult NS_NewSVGFEOffsetElement(nsIContent **aResult,
    2491                 :                                            already_AddRefed<nsINodeInfo> aNodeInfo);
    2492                 : protected:
    2493               0 :   nsSVGFEOffsetElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2494               0 :     : nsSVGFEOffsetElementBase(aNodeInfo) {}
    2495                 : 
    2496                 : public:
    2497                 :   // interfaces:
    2498                 :   NS_DECL_ISUPPORTS_INHERITED
    2499                 : 
    2500                 :   // FE Base
    2501               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEOffsetElementBase::)
    2502                 : 
    2503                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    2504                 :                           const nsTArray<const Image*>& aSources,
    2505                 :                           const Image* aTarget,
    2506                 :                           const nsIntRect& aDataRect);
    2507                 :   virtual bool AttributeAffectsRendering(
    2508                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    2509               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    2510                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    2511                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    2512                 :           const nsSVGFilterInstance& aInstance);
    2513                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    2514                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
    2515                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    2516                 :           const nsSVGFilterInstance& aInstance);
    2517                 : 
    2518                 :   // Offset
    2519                 :   NS_DECL_NSIDOMSVGFEOFFSETELEMENT
    2520                 : 
    2521               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEOffsetElementBase::)
    2522                 : 
    2523               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEOffsetElementBase::)
    2524               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEOffsetElementBase::)
    2525                 : 
    2526                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2527                 : 
    2528                 :   virtual nsXPCClassInfo* GetClassInfo();
    2529                 : protected:
    2530                 :   nsIntPoint GetOffset(const nsSVGFilterInstance& aInstance);
    2531                 :   
    2532                 :   virtual NumberAttributesInfo GetNumberInfo();
    2533                 :   virtual StringAttributesInfo GetStringInfo();
    2534                 : 
    2535                 :   enum { DX, DY };
    2536                 :   nsSVGNumber2 mNumberAttributes[2];
    2537                 :   static NumberInfo sNumberInfo[2];
    2538                 : 
    2539                 :   enum { RESULT, IN1 };
    2540                 :   nsSVGString mStringAttributes[2];
    2541                 :   static StringInfo sStringInfo[2];
    2542                 : };
    2543                 : 
    2544                 : nsSVGElement::NumberInfo nsSVGFEOffsetElement::sNumberInfo[2] =
    2545                 : {
    2546                 :   { &nsGkAtoms::dx, 0, false },
    2547                 :   { &nsGkAtoms::dy, 0, false }
    2548                 : };
    2549                 : 
    2550                 : nsSVGElement::StringInfo nsSVGFEOffsetElement::sStringInfo[2] =
    2551                 : {
    2552                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    2553                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    2554                 : };
    2555                 : 
    2556               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEOffset)
    2557                 : 
    2558                 : //----------------------------------------------------------------------
    2559                 : // nsISupports methods
    2560                 : 
    2561               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEOffsetElement,nsSVGFEOffsetElementBase)
    2562               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEOffsetElement,nsSVGFEOffsetElementBase)
    2563                 : 
    2564               0 : DOMCI_NODE_DATA(SVGFEOffsetElement, nsSVGFEOffsetElement)
    2565                 : 
    2566               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEOffsetElement)
    2567               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEOffsetElement, nsIDOMNode, nsIDOMElement,
    2568                 :                            nsIDOMSVGElement,
    2569                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    2570                 :                            nsIDOMSVGFEOffsetElement)
    2571               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEOffsetElement)
    2572               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEOffsetElementBase)
    2573                 : 
    2574                 : //----------------------------------------------------------------------
    2575                 : // nsIDOMNode methods
    2576                 : 
    2577                 : 
    2578               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEOffsetElement)
    2579                 : 
    2580                 : 
    2581                 : //----------------------------------------------------------------------
    2582                 : // nsIDOMSVGFEOffsetElement methods
    2583                 : 
    2584                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    2585               0 : NS_IMETHODIMP nsSVGFEOffsetElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    2586                 : {
    2587               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    2588                 : }
    2589                 : 
    2590                 : /* readonly attribute nsIDOMSVGAnimatedNumber dx; */
    2591               0 : NS_IMETHODIMP nsSVGFEOffsetElement::GetDx(nsIDOMSVGAnimatedNumber * *aDx)
    2592                 : {
    2593               0 :   return mNumberAttributes[DX].ToDOMAnimatedNumber(aDx, this);
    2594                 : }
    2595                 : 
    2596                 : /* readonly attribute nsIDOMSVGAnimatedNumber dy; */
    2597               0 : NS_IMETHODIMP nsSVGFEOffsetElement::GetDy(nsIDOMSVGAnimatedNumber * *aDy)
    2598                 : {
    2599               0 :   return mNumberAttributes[DY].ToDOMAnimatedNumber(aDy, this);
    2600                 : }
    2601                 : 
    2602                 : nsIntPoint
    2603               0 : nsSVGFEOffsetElement::GetOffset(const nsSVGFilterInstance& aInstance)
    2604                 : {
    2605                 :   return nsIntPoint(PRInt32(aInstance.GetPrimitiveNumber(
    2606               0 :                               nsSVGUtils::X, &mNumberAttributes[DX])),
    2607                 :                     PRInt32(aInstance.GetPrimitiveNumber(
    2608               0 :                               nsSVGUtils::Y, &mNumberAttributes[DY])));
    2609                 : }
    2610                 : 
    2611                 : nsresult
    2612               0 : nsSVGFEOffsetElement::Filter(nsSVGFilterInstance *instance,
    2613                 :                              const nsTArray<const Image*>& aSources,
    2614                 :                              const Image* aTarget,
    2615                 :                              const nsIntRect& rect)
    2616                 : {
    2617               0 :   nsIntPoint offset = GetOffset(*instance);
    2618                 : 
    2619               0 :   gfxContext ctx(aTarget->mImage);
    2620               0 :   ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
    2621                 :   // Ensure rendering is limited to the filter primitive subregion
    2622               0 :   ctx.Clip(aTarget->mFilterPrimitiveSubregion);
    2623               0 :   ctx.Translate(gfxPoint(offset.x, offset.y));
    2624               0 :   ctx.SetSource(aSources[0]->mImage);
    2625               0 :   ctx.Paint();
    2626                 : 
    2627               0 :   return NS_OK;
    2628                 : }
    2629                 : 
    2630                 : bool
    2631               0 : nsSVGFEOffsetElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    2632                 :                                                 nsIAtom* aAttribute) const
    2633                 : {
    2634               0 :   return nsSVGFEOffsetElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    2635                 :          (aNameSpaceID == kNameSpaceID_None &&
    2636                 :           (aAttribute == nsGkAtoms::in ||
    2637                 :            aAttribute == nsGkAtoms::dx ||
    2638               0 :            aAttribute == nsGkAtoms::dy));
    2639                 : }
    2640                 : 
    2641                 : void
    2642               0 : nsSVGFEOffsetElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    2643                 : {
    2644               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    2645               0 : }
    2646                 : 
    2647                 : nsIntRect
    2648               0 : nsSVGFEOffsetElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    2649                 :         const nsSVGFilterInstance& aInstance)
    2650                 : {
    2651               0 :   return aSourceBBoxes[0] + GetOffset(aInstance);
    2652                 : }
    2653                 : 
    2654                 : nsIntRect
    2655               0 : nsSVGFEOffsetElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    2656                 :                                         const nsSVGFilterInstance& aInstance)
    2657                 : {
    2658               0 :   return aSourceChangeBoxes[0] + GetOffset(aInstance);
    2659                 : }
    2660                 : 
    2661                 : void
    2662               0 : nsSVGFEOffsetElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    2663                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
    2664                 : {
    2665               0 :   aSourceBBoxes[0] = aTargetBBox - GetOffset(aInstance);
    2666               0 : }
    2667                 : 
    2668                 : //----------------------------------------------------------------------
    2669                 : // nsSVGElement methods
    2670                 : 
    2671                 : nsSVGElement::NumberAttributesInfo
    2672               0 : nsSVGFEOffsetElement::GetNumberInfo()
    2673                 : {
    2674                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    2675               0 :                               ArrayLength(sNumberInfo));
    2676                 : }
    2677                 : 
    2678                 : nsSVGElement::StringAttributesInfo
    2679               0 : nsSVGFEOffsetElement::GetStringInfo()
    2680                 : {
    2681                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    2682               0 :                               ArrayLength(sStringInfo));
    2683                 : }
    2684                 : 
    2685                 : //---------------------Flood------------------------
    2686                 : 
    2687                 : typedef nsSVGFE nsSVGFEFloodElementBase;
    2688                 : 
    2689                 : class nsSVGFEFloodElement : public nsSVGFEFloodElementBase,
    2690                 :                             public nsIDOMSVGFEFloodElement
    2691               0 : {
    2692                 :   friend nsresult NS_NewSVGFEFloodElement(nsIContent **aResult,
    2693                 :                                           already_AddRefed<nsINodeInfo> aNodeInfo);
    2694                 : protected:
    2695               0 :   nsSVGFEFloodElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2696               0 :     : nsSVGFEFloodElementBase(aNodeInfo) {}
    2697                 : 
    2698                 : public:
    2699               0 :   virtual bool SubregionIsUnionOfRegions() { return false; }
    2700                 : 
    2701                 :   // interfaces:
    2702                 :   NS_DECL_ISUPPORTS_INHERITED
    2703                 : 
    2704                 :   // FE Base
    2705               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEFloodElementBase::)
    2706                 : 
    2707                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    2708                 :                           const nsTArray<const Image*>& aSources,
    2709                 :                           const Image* aTarget,
    2710                 :                           const nsIntRect& aDataRect);
    2711               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    2712                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    2713                 :           const nsSVGFilterInstance& aInstance);
    2714                 : 
    2715                 :   // Flood
    2716                 :   NS_DECL_NSIDOMSVGFEFLOODELEMENT
    2717                 : 
    2718               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEFloodElementBase::)
    2719                 :   
    2720               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEFloodElementBase::)
    2721               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEFloodElementBase::)
    2722                 : 
    2723                 :   // nsIContent interface
    2724                 :   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
    2725                 : 
    2726                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2727                 : 
    2728                 :   virtual nsXPCClassInfo* GetClassInfo();
    2729                 : protected:
    2730               0 :   virtual bool OperatesOnSRGB(nsSVGFilterInstance*,
    2731               0 :                                 PRInt32, Image*) { return true; }
    2732                 : 
    2733                 :   virtual StringAttributesInfo GetStringInfo();
    2734                 : 
    2735                 :   enum { RESULT };
    2736                 :   nsSVGString mStringAttributes[1];
    2737                 :   static StringInfo sStringInfo[1];
    2738                 : };
    2739                 :  
    2740                 : nsSVGElement::StringInfo nsSVGFEFloodElement::sStringInfo[1] =
    2741                 : {
    2742                 :   { &nsGkAtoms::result, kNameSpaceID_None, true }
    2743                 : };
    2744                 : 
    2745               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEFlood)
    2746                 : 
    2747                 : //----------------------------------------------------------------------
    2748                 : // nsISupports methods
    2749                 : 
    2750               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEFloodElement,nsSVGFEFloodElementBase)
    2751               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEFloodElement,nsSVGFEFloodElementBase)
    2752                 : 
    2753               0 : DOMCI_NODE_DATA(SVGFEFloodElement, nsSVGFEFloodElement)
    2754                 : 
    2755               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEFloodElement)
    2756               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEFloodElement, nsIDOMNode, nsIDOMElement,
    2757                 :                            nsIDOMSVGElement,
    2758                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    2759                 :                            nsIDOMSVGFEFloodElement)
    2760               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEFloodElement)
    2761               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEFloodElementBase)
    2762                 : 
    2763                 : //----------------------------------------------------------------------
    2764                 : // nsIDOMNode methods
    2765                 : 
    2766               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFloodElement)
    2767                 : 
    2768                 : 
    2769                 : //----------------------------------------------------------------------
    2770                 : // nsIDOMSVGFEFloodElement methods
    2771                 : 
    2772                 : nsresult
    2773               0 : nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance,
    2774                 :                             const nsTArray<const Image*>& aSources,
    2775                 :                             const Image* aTarget,
    2776                 :                             const nsIntRect& aDataRect)
    2777                 : {
    2778               0 :   nsIFrame* frame = GetPrimaryFrame();
    2779               0 :   if (!frame) return NS_ERROR_FAILURE;
    2780               0 :   nsStyleContext* style = frame->GetStyleContext();
    2781                 : 
    2782               0 :   nscolor floodColor = style->GetStyleSVGReset()->mFloodColor;
    2783               0 :   float floodOpacity = style->GetStyleSVGReset()->mFloodOpacity;
    2784                 : 
    2785               0 :   gfxContext ctx(aTarget->mImage);
    2786                 :   ctx.SetColor(gfxRGBA(NS_GET_R(floodColor) / 255.0,
    2787                 :                        NS_GET_G(floodColor) / 255.0,
    2788                 :                        NS_GET_B(floodColor) / 255.0,
    2789               0 :                        NS_GET_A(floodColor) / 255.0 * floodOpacity));
    2790               0 :   ctx.Rectangle(aTarget->mFilterPrimitiveSubregion);
    2791               0 :   ctx.Fill();
    2792               0 :   return NS_OK;
    2793                 : }
    2794                 : 
    2795                 : nsIntRect
    2796               0 : nsSVGFEFloodElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    2797                 :         const nsSVGFilterInstance& aInstance)
    2798                 : {
    2799               0 :   return GetMaxRect();
    2800                 : }
    2801                 : 
    2802                 : //----------------------------------------------------------------------
    2803                 : // nsIContent methods
    2804                 : 
    2805                 : NS_IMETHODIMP_(bool)
    2806               0 : nsSVGFEFloodElement::IsAttributeMapped(const nsIAtom* name) const
    2807                 : {
    2808                 :   static const MappedAttributeEntry* const map[] = {
    2809                 :     sFEFloodMap
    2810                 :   };
    2811                 :   
    2812               0 :   return FindAttributeDependence(name, map) ||
    2813               0 :     nsSVGFEFloodElementBase::IsAttributeMapped(name);
    2814                 : }
    2815                 : 
    2816                 : //----------------------------------------------------------------------
    2817                 : // nsSVGElement methods
    2818                 : 
    2819                 : nsSVGElement::StringAttributesInfo
    2820               0 : nsSVGFEFloodElement::GetStringInfo()
    2821                 : {
    2822                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    2823               0 :                               ArrayLength(sStringInfo));
    2824                 : }
    2825                 : 
    2826                 : //---------------------Tile------------------------
    2827                 : 
    2828                 : typedef nsSVGFE nsSVGFETileElementBase;
    2829                 : 
    2830                 : class nsSVGFETileElement : public nsSVGFETileElementBase,
    2831                 :                            public nsIDOMSVGFETileElement
    2832               0 : {
    2833                 :   friend nsresult NS_NewSVGFETileElement(nsIContent **aResult,
    2834                 :                                          already_AddRefed<nsINodeInfo> aNodeInfo);
    2835                 : protected:
    2836               0 :   nsSVGFETileElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2837               0 :     : nsSVGFETileElementBase(aNodeInfo) {}
    2838                 : 
    2839                 : public:
    2840               0 :   virtual bool SubregionIsUnionOfRegions() { return false; }
    2841                 : 
    2842                 :   // interfaces:
    2843                 :   NS_DECL_ISUPPORTS_INHERITED
    2844                 : 
    2845                 :   // FE Base
    2846               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETileElementBase::)
    2847                 : 
    2848                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    2849                 :                           const nsTArray<const Image*>& aSources,
    2850                 :                           const Image* aTarget,
    2851                 :                           const nsIntRect& aDataRect);
    2852                 :   virtual bool AttributeAffectsRendering(
    2853                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    2854               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    2855                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    2856                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    2857                 :           const nsSVGFilterInstance& aInstance);
    2858                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    2859                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
    2860                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    2861                 :           const nsSVGFilterInstance& aInstance);
    2862                 : 
    2863                 :   // Tile
    2864                 :   NS_DECL_NSIDOMSVGFETILEELEMENT
    2865                 : 
    2866               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETileElementBase::)
    2867                 : 
    2868               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFETileElementBase::)
    2869               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFETileElementBase::)
    2870                 : 
    2871                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    2872                 : 
    2873                 :   virtual nsXPCClassInfo* GetClassInfo();
    2874                 : protected:
    2875                 :   virtual StringAttributesInfo GetStringInfo();
    2876                 :   
    2877                 :   enum { RESULT, IN1 };
    2878                 :   nsSVGString mStringAttributes[2];
    2879                 :   static StringInfo sStringInfo[2];
    2880                 : };
    2881                 : 
    2882                 : nsSVGElement::StringInfo nsSVGFETileElement::sStringInfo[2] =
    2883                 : {
    2884                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    2885                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    2886                 : };
    2887                 : 
    2888               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FETile)
    2889                 : 
    2890                 : //----------------------------------------------------------------------
    2891                 : // nsISupports methods
    2892                 : 
    2893               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFETileElement,nsSVGFETileElementBase)
    2894               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFETileElement,nsSVGFETileElementBase)
    2895                 : 
    2896               0 : DOMCI_NODE_DATA(SVGFETileElement, nsSVGFETileElement)
    2897                 : 
    2898               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFETileElement)
    2899               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFETileElement, nsIDOMNode, nsIDOMElement,
    2900                 :                            nsIDOMSVGElement,
    2901                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    2902                 :                            nsIDOMSVGFETileElement)
    2903               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETileElement)
    2904               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFETileElementBase)
    2905                 : 
    2906                 : //----------------------------------------------------------------------
    2907                 : // nsIDOMNode methods
    2908                 : 
    2909                 : 
    2910               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETileElement)
    2911                 : 
    2912                 : 
    2913                 : //----------------------------------------------------------------------
    2914                 : // nsSVGFETileElement methods
    2915                 : 
    2916                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    2917               0 : NS_IMETHODIMP nsSVGFETileElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    2918                 : {
    2919               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    2920                 : }
    2921                 : 
    2922                 : void
    2923               0 : nsSVGFETileElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    2924                 : {
    2925               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    2926               0 : }
    2927                 : 
    2928                 : nsIntRect
    2929               0 : nsSVGFETileElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    2930                 :         const nsSVGFilterInstance& aInstance)
    2931                 : {
    2932               0 :   return GetMaxRect();
    2933                 : }
    2934                 : 
    2935                 : void
    2936               0 : nsSVGFETileElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    2937                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
    2938                 : {
    2939                 :   // Just assume we need the entire source bounding box, so do nothing.
    2940               0 : }
    2941                 : 
    2942                 : nsIntRect
    2943               0 : nsSVGFETileElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    2944                 :                                       const nsSVGFilterInstance& aInstance)
    2945                 : {
    2946               0 :   return GetMaxRect();
    2947                 : }
    2948                 : 
    2949               0 : static PRInt32 WrapInterval(PRInt32 aVal, PRInt32 aMax)
    2950                 : {
    2951               0 :   aVal = aVal % aMax;
    2952               0 :   return aVal < 0 ? aMax + aVal : aVal;
    2953                 : }
    2954                 : 
    2955                 : //----------------------------------------------------------------------
    2956                 : // nsSVGElement methods
    2957                 : 
    2958                 : nsresult
    2959               0 : nsSVGFETileElement::Filter(nsSVGFilterInstance *instance,
    2960                 :                            const nsTArray<const Image*>& aSources,
    2961                 :                            const Image* aTarget,
    2962                 :                            const nsIntRect& rect)
    2963                 : {
    2964                 :   // XXX This code depends on the surface rect containing the filter
    2965                 :   // primitive subregion. ComputeTargetBBox, ComputeNeededSourceBBoxes
    2966                 :   // and ComputeChangeBBox are all pessimal, so that will normally be OK,
    2967                 :   // but nothing clips mFilterPrimitiveSubregion so this should be changed.
    2968                 : 
    2969               0 :   nsIntRect tile;
    2970               0 :   bool res = gfxUtils::GfxRectToIntRect(aSources[0]->mFilterPrimitiveSubregion, &tile);
    2971                 : 
    2972               0 :   NS_ENSURE_TRUE(res, NS_ERROR_FAILURE); // asserts on failure (not 
    2973               0 :   if (tile.IsEmpty())
    2974               0 :     return NS_OK;
    2975                 : 
    2976               0 :   const nsIntRect &surfaceRect = instance->GetSurfaceRect();
    2977               0 :   if (!tile.Intersects(surfaceRect)) {
    2978                 :     // nothing to draw
    2979               0 :     return NS_OK;
    2980                 :   }
    2981                 : 
    2982                 :   // Get it into surface space
    2983               0 :   tile -= surfaceRect.TopLeft();
    2984                 : 
    2985               0 :   PRUint8* sourceData = aSources[0]->mImage->Data();
    2986               0 :   PRUint8* targetData = aTarget->mImage->Data();
    2987               0 :   PRUint32 stride = aTarget->mImage->Stride();
    2988                 : 
    2989                 :   // the offset to add to our x/y coordinates (which are relative to the
    2990                 :   // temporary surface data) to get coordinates relative to the origin
    2991                 :   // of the tile
    2992               0 :   nsIntPoint offset(-tile.x + tile.width, -tile.y + tile.height);
    2993               0 :   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    2994               0 :     PRUint32 tileY = tile.y + WrapInterval(y + offset.y, tile.height);
    2995               0 :     if (tileY < (PRUint32)surfaceRect.height) {
    2996               0 :       for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    2997               0 :         PRUint32 tileX = tile.x + WrapInterval(x + offset.x, tile.width);
    2998               0 :         if (tileX < (PRUint32)surfaceRect.width) {
    2999               0 :           *(PRUint32*)(targetData + y * stride + 4 * x) =
    3000               0 :             *(PRUint32*)(sourceData + tileY * stride + 4 * tileX);
    3001                 :         }
    3002                 :       }
    3003                 :     }
    3004                 :   }
    3005                 : 
    3006               0 :   return NS_OK;
    3007                 : }
    3008                 : 
    3009                 : bool
    3010               0 : nsSVGFETileElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    3011                 :                                               nsIAtom* aAttribute) const
    3012                 : {
    3013               0 :   return nsSVGFETileElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    3014                 :          (aNameSpaceID == kNameSpaceID_None &&
    3015               0 :           aAttribute == nsGkAtoms::in);
    3016                 : }
    3017                 : 
    3018                 : //----------------------------------------------------------------------
    3019                 : // nsSVGElement methods
    3020                 : 
    3021                 : nsSVGElement::StringAttributesInfo
    3022               0 : nsSVGFETileElement::GetStringInfo()
    3023                 : {
    3024                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    3025               0 :                               ArrayLength(sStringInfo));
    3026                 : }
    3027                 : 
    3028                 : //---------------------Turbulence------------------------
    3029                 : 
    3030                 : typedef nsSVGFE nsSVGFETurbulenceElementBase;
    3031                 : 
    3032                 : class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase,
    3033                 :                                  public nsIDOMSVGFETurbulenceElement
    3034               0 : {
    3035                 :   friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult,
    3036                 :                                                already_AddRefed<nsINodeInfo> aNodeInfo);
    3037                 : protected:
    3038               0 :   nsSVGFETurbulenceElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    3039               0 :     : nsSVGFETurbulenceElementBase(aNodeInfo) {}
    3040                 : 
    3041                 : public:
    3042               0 :   virtual bool SubregionIsUnionOfRegions() { return false; }
    3043                 : 
    3044                 :   // interfaces:
    3045                 :   NS_DECL_ISUPPORTS_INHERITED
    3046                 : 
    3047                 :   // FE Base
    3048               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::)
    3049                 : 
    3050                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    3051                 :                           const nsTArray<const Image*>& aSources,
    3052                 :                           const Image* aTarget,
    3053                 :                           const nsIntRect& aDataRect);
    3054                 :   virtual bool AttributeAffectsRendering(
    3055                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    3056               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    3057                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    3058                 :           const nsSVGFilterInstance& aInstance);
    3059                 : 
    3060                 :   // Turbulence
    3061                 :   NS_DECL_NSIDOMSVGFETURBULENCEELEMENT
    3062                 : 
    3063               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::)
    3064                 : 
    3065               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFETurbulenceElementBase::)
    3066               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFETurbulenceElementBase::)
    3067                 : 
    3068                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    3069                 : 
    3070                 :   virtual nsXPCClassInfo* GetClassInfo();
    3071                 : protected:
    3072                 :   virtual NumberAttributesInfo GetNumberInfo();
    3073                 :   virtual NumberPairAttributesInfo GetNumberPairInfo();
    3074                 :   virtual IntegerAttributesInfo GetIntegerInfo();
    3075                 :   virtual EnumAttributesInfo GetEnumInfo();
    3076                 :   virtual StringAttributesInfo GetStringInfo();
    3077                 : 
    3078                 :   enum { SEED }; // floating point seed?!
    3079                 :   nsSVGNumber2 mNumberAttributes[1];
    3080                 :   static NumberInfo sNumberInfo[1];
    3081                 : 
    3082                 :   enum { BASE_FREQ };
    3083                 :   nsSVGNumberPair mNumberPairAttributes[1];
    3084                 :   static NumberPairInfo sNumberPairInfo[1];
    3085                 : 
    3086                 :   enum { OCTAVES };
    3087                 :   nsSVGInteger mIntegerAttributes[1];
    3088                 :   static IntegerInfo sIntegerInfo[1];
    3089                 : 
    3090                 :   enum { TYPE, STITCHTILES };
    3091                 :   nsSVGEnum mEnumAttributes[2];
    3092                 :   static nsSVGEnumMapping sTypeMap[];
    3093                 :   static nsSVGEnumMapping sStitchTilesMap[];
    3094                 :   static EnumInfo sEnumInfo[2];
    3095                 : 
    3096                 :   enum { RESULT };
    3097                 :   nsSVGString mStringAttributes[1];
    3098                 :   static StringInfo sStringInfo[1];
    3099                 : 
    3100                 : private:
    3101                 : 
    3102                 :   /* The turbulence calculation code is an adapted version of what
    3103                 :      appears in the SVG 1.1 specification:
    3104                 :          http://www.w3.org/TR/SVG11/filters.html#feTurbulence
    3105                 :   */
    3106                 : 
    3107                 :   /* Produces results in the range [1, 2**31 - 2].
    3108                 :      Algorithm is: r = (a * r) mod m
    3109                 :      where a = 16807 and m = 2**31 - 1 = 2147483647
    3110                 :      See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
    3111                 :      To test: the algorithm should produce the result 1043618065
    3112                 :      as the 10,000th generated number if the original seed is 1.
    3113                 :   */
    3114                 : #define RAND_M 2147483647       /* 2**31 - 1 */
    3115                 : #define RAND_A 16807            /* 7**5; primitive root of m */
    3116                 : #define RAND_Q 127773           /* m / a */
    3117                 : #define RAND_R 2836             /* m % a */
    3118                 : 
    3119               0 :   PRInt32 SetupSeed(PRInt32 aSeed) {
    3120               0 :     if (aSeed <= 0)
    3121               0 :       aSeed = -(aSeed % (RAND_M - 1)) + 1;
    3122               0 :     if (aSeed > RAND_M - 1)
    3123               0 :       aSeed = RAND_M - 1;
    3124               0 :     return aSeed;
    3125                 :   }
    3126                 : 
    3127               0 :   PRUint32 Random(PRUint32 aSeed) {
    3128               0 :     PRInt32 result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q);
    3129               0 :     if (result <= 0)
    3130               0 :       result += RAND_M;
    3131               0 :     return result;
    3132                 :   }
    3133                 : #undef RAND_M
    3134                 : #undef RAND_A
    3135                 : #undef RAND_Q
    3136                 : #undef RAND_R
    3137                 : 
    3138                 :   const static int sBSize = 0x100;
    3139                 :   const static int sBM = 0xff;
    3140                 :   const static int sPerlinN = 0x1000;
    3141                 :   const static int sNP = 12;                    /* 2^PerlinN */
    3142                 :   const static int sNM = 0xfff;
    3143                 : 
    3144                 :   PRInt32 mLatticeSelector[sBSize + sBSize + 2];
    3145                 :   double mGradient[4][sBSize + sBSize + 2][2];
    3146                 :   struct StitchInfo {
    3147                 :     int mWidth;                 // How much to subtract to wrap for stitching.
    3148                 :     int mHeight;
    3149                 :     int mWrapX;                 // Minimum value to wrap.
    3150                 :     int mWrapY;
    3151                 :   };
    3152                 : 
    3153                 :   void InitSeed(PRInt32 aSeed);
    3154                 :   double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo);
    3155                 :   double
    3156                 :   Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX,
    3157                 :              double aBaseFreqY, int aNumOctaves, bool aFractalSum,
    3158                 :              bool aDoStitching, double aTileX, double aTileY,
    3159                 :              double aTileWidth, double aTileHeight);
    3160                 : };
    3161                 : 
    3162                 : nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] =
    3163                 : {
    3164                 :   { &nsGkAtoms::seed, 0, false }
    3165                 : };
    3166                 : 
    3167                 : nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] =
    3168                 : {
    3169                 :   { &nsGkAtoms::baseFrequency, 0, 0 }
    3170                 : };
    3171                 : 
    3172                 : nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] =
    3173                 : {
    3174                 :   { &nsGkAtoms::numOctaves, 1 }
    3175                 : };
    3176                 : 
    3177                 : nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = {
    3178                 :   {&nsGkAtoms::fractalNoise,
    3179                 :    nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE},
    3180                 :   {&nsGkAtoms::turbulence,
    3181                 :    nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE},
    3182                 :   {nsnull, 0}
    3183                 : };
    3184                 : 
    3185                 : nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = {
    3186                 :   {&nsGkAtoms::stitch,
    3187                 :    nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH},
    3188                 :   {&nsGkAtoms::noStitch,
    3189                 :    nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH},
    3190                 :   {nsnull, 0}
    3191                 : };
    3192                 : 
    3193                 : nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] =
    3194                 : {
    3195                 :   { &nsGkAtoms::type,
    3196                 :     sTypeMap,
    3197                 :     nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE
    3198                 :   },
    3199                 :   { &nsGkAtoms::stitchTiles,
    3200                 :     sStitchTilesMap,
    3201                 :     nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH
    3202                 :   }
    3203                 : };
    3204                 : 
    3205                 : nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] =
    3206                 : {
    3207                 :   { &nsGkAtoms::result, kNameSpaceID_None, true }
    3208                 : };
    3209                 : 
    3210               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)
    3211                 : 
    3212                 : //----------------------------------------------------------------------
    3213                 : // nsISupports methods
    3214                 : 
    3215               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
    3216               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
    3217                 : 
    3218               0 : DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement)
    3219                 : 
    3220               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement)
    3221               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement,
    3222                 :                            nsIDOMSVGElement,
    3223                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    3224                 :                            nsIDOMSVGFETurbulenceElement)
    3225               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement)
    3226               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase)
    3227                 : 
    3228                 : //----------------------------------------------------------------------
    3229                 : // nsIDOMNode methods
    3230                 : 
    3231               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement)
    3232                 : 
    3233                 : //----------------------------------------------------------------------
    3234                 : // nsIDOMSVGFETurbulenceElement methods
    3235                 : 
    3236                 : /* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */
    3237               0 : NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX)
    3238                 : {
    3239               0 :   return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
    3240                 : }
    3241                 : 
    3242                 : /* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */
    3243               0 : NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY)
    3244                 : {
    3245               0 :   return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
    3246                 : }
    3247                 : 
    3248                 : /* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */
    3249               0 : NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum)
    3250                 : {
    3251               0 :   return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this);
    3252                 : }
    3253                 : 
    3254                 : /* readonly attribute nsIDOMSVGAnimatedNumber seed; */
    3255               0 : NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed)
    3256                 : {
    3257               0 :   return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this);
    3258                 : }
    3259                 : 
    3260                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */
    3261               0 : NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch)
    3262                 : {
    3263               0 :   return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this);
    3264                 : }
    3265                 : 
    3266                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
    3267               0 : NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
    3268                 : {
    3269               0 :   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
    3270                 : }
    3271                 : 
    3272                 : nsresult
    3273               0 : nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
    3274                 :                                  const nsTArray<const Image*>& aSources,
    3275                 :                                  const Image* aTarget,
    3276                 :                                  const nsIntRect& rect)
    3277                 : {
    3278               0 :   PRUint8* targetData = aTarget->mImage->Data();
    3279               0 :   PRUint32 stride = aTarget->mImage->Stride();
    3280                 : 
    3281               0 :   nsIntRect filterSubregion(PRInt32(aTarget->mFilterPrimitiveSubregion.X()),
    3282               0 :                             PRInt32(aTarget->mFilterPrimitiveSubregion.Y()),
    3283               0 :                             PRInt32(aTarget->mFilterPrimitiveSubregion.Width()),
    3284               0 :                             PRInt32(aTarget->mFilterPrimitiveSubregion.Height()));
    3285                 : 
    3286               0 :   float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eFirst);
    3287               0 :   float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eSecond);
    3288               0 :   float seed = mNumberAttributes[OCTAVES].GetAnimValue();
    3289               0 :   PRInt32 octaves = mIntegerAttributes[OCTAVES].GetAnimValue();
    3290               0 :   PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
    3291               0 :   PRUint16 stitch = mEnumAttributes[STITCHTILES].GetAnimValue();
    3292                 : 
    3293               0 :   InitSeed((PRInt32)seed);
    3294                 : 
    3295                 :   // XXXroc this makes absolutely no sense to me.
    3296               0 :   float filterX = instance->GetFilterRect().X();
    3297               0 :   float filterY = instance->GetFilterRect().Y();
    3298               0 :   float filterWidth = instance->GetFilterRect().Width();
    3299               0 :   float filterHeight = instance->GetFilterRect().Height();
    3300                 : 
    3301               0 :   bool doStitch = false;
    3302               0 :   if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) {
    3303               0 :     doStitch = true;
    3304                 : 
    3305                 :     float lowFreq, hiFreq;
    3306                 : 
    3307               0 :     lowFreq = floor(filterWidth * fX) / filterWidth;
    3308               0 :     hiFreq = ceil(filterWidth * fX) / filterWidth;
    3309               0 :     if (fX / lowFreq < hiFreq / fX)
    3310               0 :       fX = lowFreq;
    3311                 :     else
    3312               0 :       fX = hiFreq;
    3313                 : 
    3314               0 :     lowFreq = floor(filterHeight * fY) / filterHeight;
    3315               0 :     hiFreq = ceil(filterHeight * fY) / filterHeight;
    3316               0 :     if (fY / lowFreq < hiFreq / fY)
    3317               0 :       fY = lowFreq;
    3318                 :     else
    3319               0 :       fY = hiFreq;
    3320                 :   }
    3321               0 :   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    3322               0 :     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    3323               0 :       PRInt32 targIndex = y * stride + x * 4;
    3324                 :       double point[2];
    3325               0 :       point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1);
    3326               0 :       point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1);
    3327                 : 
    3328                 :       float col[4];
    3329               0 :       if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) {
    3330               0 :         for (int i = 0; i < 4; i++)
    3331                 :           col[i] = Turbulence(i, point, fX, fY, octaves, false,
    3332               0 :                               doStitch, filterX, filterY, filterWidth, filterHeight) * 255;
    3333                 :       } else {
    3334               0 :         for (int i = 0; i < 4; i++)
    3335                 :           col[i] = (Turbulence(i, point, fX, fY, octaves, true,
    3336               0 :                                doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2;
    3337                 :       }
    3338               0 :       for (int i = 0; i < 4; i++) {
    3339               0 :         col[i] = NS_MIN(col[i], 255.f);
    3340               0 :         col[i] = NS_MAX(col[i], 0.f);
    3341                 :       }
    3342                 : 
    3343                 :       PRUint8 r, g, b, a;
    3344               0 :       a = PRUint8(col[3]);
    3345               0 :       FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a);
    3346               0 :       FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a);
    3347               0 :       FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a);
    3348                 : 
    3349               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_B] = b;
    3350               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_G] = g;
    3351               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_R] = r;
    3352               0 :       targetData[targIndex + GFX_ARGB32_OFFSET_A] = a;
    3353                 :     }
    3354                 :   }
    3355                 : 
    3356               0 :   return NS_OK;
    3357                 : }
    3358                 : 
    3359                 : bool
    3360               0 : nsSVGFETurbulenceElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    3361                 :                                                     nsIAtom* aAttribute) const
    3362                 : {
    3363               0 :   return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    3364                 :          (aNameSpaceID == kNameSpaceID_None &&
    3365                 :           (aAttribute == nsGkAtoms::seed ||
    3366                 :            aAttribute == nsGkAtoms::baseFrequency ||
    3367                 :            aAttribute == nsGkAtoms::numOctaves ||
    3368                 :            aAttribute == nsGkAtoms::type ||
    3369               0 :            aAttribute == nsGkAtoms::stitchTiles));
    3370                 : }
    3371                 : 
    3372                 : void
    3373               0 : nsSVGFETurbulenceElement::InitSeed(PRInt32 aSeed)
    3374                 : {
    3375                 :   double s;
    3376                 :   int i, j, k;
    3377               0 :   aSeed = SetupSeed(aSeed);
    3378               0 :   for (k = 0; k < 4; k++) {
    3379               0 :     for (i = 0; i < sBSize; i++) {
    3380               0 :       mLatticeSelector[i] = i;
    3381               0 :       for (j = 0; j < 2; j++) {
    3382                 :         mGradient[k][i][j] =
    3383                 :           (double) (((aSeed =
    3384               0 :                       Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize;
    3385                 :       }
    3386                 :       s = double (sqrt
    3387               0 :                   (mGradient[k][i][0] * mGradient[k][i][0] +
    3388               0 :                    mGradient[k][i][1] * mGradient[k][i][1]));
    3389               0 :       mGradient[k][i][0] /= s;
    3390               0 :       mGradient[k][i][1] /= s;
    3391                 :     }
    3392                 :   }
    3393               0 :   while (--i) {
    3394               0 :     k = mLatticeSelector[i];
    3395                 :     mLatticeSelector[i] = mLatticeSelector[j =
    3396                 :                                            (aSeed =
    3397               0 :                                             Random(aSeed)) % sBSize];
    3398               0 :     mLatticeSelector[j] = k;
    3399                 :   }
    3400               0 :   for (i = 0; i < sBSize + 2; i++) {
    3401               0 :     mLatticeSelector[sBSize + i] = mLatticeSelector[i];
    3402               0 :     for (k = 0; k < 4; k++)
    3403               0 :       for (j = 0; j < 2; j++)
    3404               0 :         mGradient[k][sBSize + i][j] = mGradient[k][i][j];
    3405                 :   }
    3406               0 : }
    3407                 : 
    3408                 : #define S_CURVE(t) ( t * t * (3. - 2. * t) )
    3409                 : #define LERP(t, a, b) ( a + t * (b - a) )
    3410                 : double
    3411               0 : nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
    3412                 :                                  StitchInfo *aStitchInfo)
    3413                 : {
    3414                 :   int bx0, bx1, by0, by1, b00, b10, b01, b11;
    3415                 :   double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
    3416                 :   register long i, j;
    3417               0 :   t = aVec[0] + sPerlinN;
    3418               0 :   bx0 = (int) t;
    3419               0 :   bx1 = bx0 + 1;
    3420               0 :   rx0 = t - (int) t;
    3421               0 :   rx1 = rx0 - 1.0f;
    3422               0 :   t = aVec[1] + sPerlinN;
    3423               0 :   by0 = (int) t;
    3424               0 :   by1 = by0 + 1;
    3425               0 :   ry0 = t - (int) t;
    3426               0 :   ry1 = ry0 - 1.0f;
    3427                 :   // If stitching, adjust lattice points accordingly.
    3428               0 :   if (aStitchInfo != NULL) {
    3429               0 :     if (bx0 >= aStitchInfo->mWrapX)
    3430               0 :       bx0 -= aStitchInfo->mWidth;
    3431               0 :     if (bx1 >= aStitchInfo->mWrapX)
    3432               0 :       bx1 -= aStitchInfo->mWidth;
    3433               0 :     if (by0 >= aStitchInfo->mWrapY)
    3434               0 :       by0 -= aStitchInfo->mHeight;
    3435               0 :     if (by1 >= aStitchInfo->mWrapY)
    3436               0 :       by1 -= aStitchInfo->mHeight;
    3437                 :   }
    3438               0 :   bx0 &= sBM;
    3439               0 :   bx1 &= sBM;
    3440               0 :   by0 &= sBM;
    3441               0 :   by1 &= sBM;
    3442               0 :   i = mLatticeSelector[bx0];
    3443               0 :   j = mLatticeSelector[bx1];
    3444               0 :   b00 = mLatticeSelector[i + by0];
    3445               0 :   b10 = mLatticeSelector[j + by0];
    3446               0 :   b01 = mLatticeSelector[i + by1];
    3447               0 :   b11 = mLatticeSelector[j + by1];
    3448               0 :   sx = double (S_CURVE(rx0));
    3449               0 :   sy = double (S_CURVE(ry0));
    3450               0 :   q = mGradient[aColorChannel][b00];
    3451               0 :   u = rx0 * q[0] + ry0 * q[1];
    3452               0 :   q = mGradient[aColorChannel][b10];
    3453               0 :   v = rx1 * q[0] + ry0 * q[1];
    3454               0 :   a = LERP(sx, u, v);
    3455               0 :   q = mGradient[aColorChannel][b01];
    3456               0 :   u = rx0 * q[0] + ry1 * q[1];
    3457               0 :   q = mGradient[aColorChannel][b11];
    3458               0 :   v = rx1 * q[0] + ry1 * q[1];
    3459               0 :   b = LERP(sx, u, v);
    3460               0 :   return LERP(sy, a, b);
    3461                 : }
    3462                 : #undef S_CURVE
    3463                 : #undef LERP
    3464                 : 
    3465                 : double
    3466               0 : nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint,
    3467                 :                                      double aBaseFreqX, double aBaseFreqY,
    3468                 :                                      int aNumOctaves, bool aFractalSum,
    3469                 :                                      bool aDoStitching,
    3470                 :                                      double aTileX, double aTileY,
    3471                 :                                      double aTileWidth, double aTileHeight)
    3472                 : {
    3473                 :   StitchInfo stitch;
    3474               0 :   StitchInfo *stitchInfo = NULL; // Not stitching when NULL.
    3475                 :   // Adjust the base frequencies if necessary for stitching.
    3476               0 :   if (aDoStitching) {
    3477                 :     // When stitching tiled turbulence, the frequencies must be adjusted
    3478                 :     // so that the tile borders will be continuous.
    3479               0 :     if (aBaseFreqX != 0.0) {
    3480               0 :       double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth;
    3481               0 :       double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth;
    3482               0 :       if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX)
    3483               0 :         aBaseFreqX = loFreq;
    3484                 :       else
    3485               0 :         aBaseFreqX = hiFreq;
    3486                 :     }
    3487               0 :     if (aBaseFreqY != 0.0) {
    3488               0 :       double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight;
    3489               0 :       double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight;
    3490               0 :       if (aBaseFreqY / loFreq < hiFreq / aBaseFreqY)
    3491               0 :         aBaseFreqY = loFreq;
    3492                 :       else
    3493               0 :         aBaseFreqY = hiFreq;
    3494                 :     }
    3495                 :     // Set up initial stitch values.
    3496               0 :     stitchInfo = &stitch;
    3497               0 :     stitch.mWidth = int (aTileWidth * aBaseFreqX + 0.5f);
    3498               0 :     stitch.mWrapX = int (aTileX * aBaseFreqX + sPerlinN + stitch.mWidth);
    3499               0 :     stitch.mHeight = int (aTileHeight * aBaseFreqY + 0.5f);
    3500               0 :     stitch.mWrapY = int (aTileY * aBaseFreqY + sPerlinN + stitch.mHeight);
    3501                 :   }
    3502               0 :   double sum = 0.0f;
    3503                 :   double vec[2];
    3504               0 :   vec[0] = aPoint[0] * aBaseFreqX;
    3505               0 :   vec[1] = aPoint[1] * aBaseFreqY;
    3506               0 :   double ratio = 1;
    3507               0 :   for (int octave = 0; octave < aNumOctaves; octave++) {
    3508               0 :     if (aFractalSum)
    3509               0 :       sum += double (Noise2(aColorChannel, vec, stitchInfo) / ratio);
    3510                 :     else
    3511               0 :       sum += double (fabs(Noise2(aColorChannel, vec, stitchInfo)) / ratio);
    3512               0 :     vec[0] *= 2;
    3513               0 :     vec[1] *= 2;
    3514               0 :     ratio *= 2;
    3515               0 :     if (stitchInfo != NULL) {
    3516                 :       // Update stitch values. Subtracting sPerlinN before the multiplication
    3517                 :       // and adding it afterward simplifies to subtracting it once.
    3518               0 :       stitch.mWidth *= 2;
    3519               0 :       stitch.mWrapX = 2 * stitch.mWrapX - sPerlinN;
    3520               0 :       stitch.mHeight *= 2;
    3521               0 :       stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN;
    3522                 :     }
    3523                 :   }
    3524               0 :   return sum;
    3525                 : }
    3526                 : 
    3527                 : nsIntRect
    3528               0 : nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    3529                 :         const nsSVGFilterInstance& aInstance)
    3530                 : {
    3531               0 :   return GetMaxRect();
    3532                 : }
    3533                 : 
    3534                 : //----------------------------------------------------------------------
    3535                 : // nsSVGElement methods
    3536                 : 
    3537                 : nsSVGElement::NumberAttributesInfo
    3538               0 : nsSVGFETurbulenceElement::GetNumberInfo()
    3539                 : {
    3540                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    3541               0 :                               ArrayLength(sNumberInfo));
    3542                 : }
    3543                 : 
    3544                 : nsSVGElement::NumberPairAttributesInfo
    3545               0 : nsSVGFETurbulenceElement::GetNumberPairInfo()
    3546                 : {
    3547                 :   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
    3548               0 :                                  ArrayLength(sNumberPairInfo));
    3549                 : }
    3550                 : 
    3551                 : nsSVGElement::IntegerAttributesInfo
    3552               0 : nsSVGFETurbulenceElement::GetIntegerInfo()
    3553                 : {
    3554                 :   return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
    3555               0 :                                ArrayLength(sIntegerInfo));
    3556                 : }
    3557                 : 
    3558                 : nsSVGElement::EnumAttributesInfo
    3559               0 : nsSVGFETurbulenceElement::GetEnumInfo()
    3560                 : {
    3561                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    3562               0 :                             ArrayLength(sEnumInfo));
    3563                 : }
    3564                 : 
    3565                 : nsSVGElement::StringAttributesInfo
    3566               0 : nsSVGFETurbulenceElement::GetStringInfo()
    3567                 : {
    3568                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    3569               0 :                               ArrayLength(sStringInfo));
    3570                 : }
    3571                 : 
    3572                 : //---------------------Morphology------------------------
    3573                 : 
    3574                 : typedef nsSVGFE nsSVGFEMorphologyElementBase;
    3575                 : 
    3576                 : class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase,
    3577                 :                                  public nsIDOMSVGFEMorphologyElement
    3578               0 : {
    3579                 :   friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult,
    3580                 :                                                already_AddRefed<nsINodeInfo> aNodeInfo);
    3581                 : protected:
    3582               0 :   nsSVGFEMorphologyElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    3583               0 :     : nsSVGFEMorphologyElementBase(aNodeInfo) {}
    3584                 : 
    3585                 : public:
    3586                 :   // interfaces:
    3587                 :   NS_DECL_ISUPPORTS_INHERITED
    3588                 : 
    3589                 :   // FE Base
    3590               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::)
    3591                 : 
    3592                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    3593                 :                           const nsTArray<const Image*>& aSources,
    3594                 :                           const Image* aTarget,
    3595                 :                           const nsIntRect& aDataRect);
    3596                 :   virtual bool AttributeAffectsRendering(
    3597                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    3598               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    3599                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    3600                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    3601                 :           const nsSVGFilterInstance& aInstance);
    3602                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    3603                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
    3604                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    3605                 :           const nsSVGFilterInstance& aInstance);
    3606                 : 
    3607                 :   // Morphology
    3608                 :   NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT
    3609                 : 
    3610               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::)
    3611                 : 
    3612               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEMorphologyElementBase::)
    3613               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEMorphologyElementBase::)
    3614                 : 
    3615                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    3616                 : 
    3617                 :   virtual nsXPCClassInfo* GetClassInfo();
    3618                 : protected:
    3619                 :   void GetRXY(PRInt32 *aRX, PRInt32 *aRY, const nsSVGFilterInstance& aInstance);
    3620                 :   nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
    3621                 : 
    3622                 :   virtual NumberPairAttributesInfo GetNumberPairInfo();
    3623                 :   virtual EnumAttributesInfo GetEnumInfo();
    3624                 :   virtual StringAttributesInfo GetStringInfo();
    3625                 : 
    3626                 :   enum { RADIUS };
    3627                 :   nsSVGNumberPair mNumberPairAttributes[1];
    3628                 :   static NumberPairInfo sNumberPairInfo[1];
    3629                 : 
    3630                 :   enum { OPERATOR };
    3631                 :   nsSVGEnum mEnumAttributes[1];
    3632                 :   static nsSVGEnumMapping sOperatorMap[];
    3633                 :   static EnumInfo sEnumInfo[1];
    3634                 : 
    3635                 :   enum { RESULT, IN1 };
    3636                 :   nsSVGString mStringAttributes[2];
    3637                 :   static StringInfo sStringInfo[2];
    3638                 : };
    3639                 : 
    3640                 : nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] =
    3641                 : {
    3642                 :   { &nsGkAtoms::radius, 0, 0 }
    3643                 : };
    3644                 : 
    3645                 : nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = {
    3646                 :   {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE},
    3647                 :   {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE},
    3648                 :   {nsnull, 0}
    3649                 : };
    3650                 : 
    3651                 : nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] =
    3652                 : {
    3653                 :   { &nsGkAtoms::_operator,
    3654                 :     sOperatorMap,
    3655                 :     nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE
    3656                 :   }
    3657                 : };
    3658                 : 
    3659                 : nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] =
    3660                 : {
    3661                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    3662                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    3663                 : };
    3664                 : 
    3665               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology)
    3666                 : 
    3667                 : //----------------------------------------------------------------------
    3668                 : // nsISupports methods
    3669                 : 
    3670               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
    3671               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
    3672                 : 
    3673               0 : DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement)
    3674                 : 
    3675               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement)
    3676               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement,
    3677                 :                            nsIDOMSVGElement,
    3678                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    3679                 :                            nsIDOMSVGFEMorphologyElement)
    3680               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement)
    3681               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase)
    3682                 : 
    3683                 : //----------------------------------------------------------------------
    3684                 : // nsIDOMNode methods
    3685                 : 
    3686                 : 
    3687               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement)
    3688                 : 
    3689                 : 
    3690                 : //----------------------------------------------------------------------
    3691                 : // nsSVGFEMorphologyElement methods
    3692                 : 
    3693                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    3694               0 : NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    3695                 : {
    3696               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    3697                 : }
    3698                 : 
    3699                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */
    3700               0 : NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator)
    3701                 : {
    3702               0 :   return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this);
    3703                 : }
    3704                 : 
    3705                 : /* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */
    3706               0 : NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX)
    3707                 : {
    3708               0 :   return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
    3709                 : }
    3710                 : 
    3711                 : /* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */
    3712               0 : NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY)
    3713                 : {
    3714               0 :   return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
    3715                 : }
    3716                 : 
    3717                 : NS_IMETHODIMP
    3718               0 : nsSVGFEMorphologyElement::SetRadius(float rx, float ry)
    3719                 : {
    3720               0 :   NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE);
    3721               0 :   mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this);
    3722               0 :   return NS_OK;
    3723                 : }
    3724                 : 
    3725                 : void
    3726               0 : nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    3727                 : {
    3728               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    3729               0 : }
    3730                 : 
    3731                 : nsIntRect
    3732               0 : nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
    3733                 :                                       const nsSVGFilterInstance& aInstance)
    3734                 : {
    3735                 :   PRInt32 rx, ry;
    3736               0 :   GetRXY(&rx, &ry, aInstance);
    3737               0 :   nsIntRect result = aRect;
    3738               0 :   result.Inflate(NS_MAX(0, rx), NS_MAX(0, ry));
    3739                 :   return result;
    3740                 : }
    3741                 : 
    3742                 : nsIntRect
    3743               0 : nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    3744                 :         const nsSVGFilterInstance& aInstance)
    3745                 : {
    3746               0 :   return InflateRect(aSourceBBoxes[0], aInstance);
    3747                 : }
    3748                 : 
    3749                 : void
    3750               0 : nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    3751                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
    3752                 : {
    3753               0 :   aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance);
    3754               0 : }
    3755                 : 
    3756                 : nsIntRect
    3757               0 : nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    3758                 :                                             const nsSVGFilterInstance& aInstance)
    3759                 : {
    3760               0 :   return InflateRect(aSourceChangeBoxes[0], aInstance);
    3761                 : }
    3762                 : 
    3763                 : #define MORPHOLOGY_EPSILON 0.0001
    3764                 : 
    3765                 : void
    3766               0 : nsSVGFEMorphologyElement::GetRXY(PRInt32 *aRX, PRInt32 *aRY,
    3767                 :                                  const nsSVGFilterInstance& aInstance)
    3768                 : {
    3769                 :   // Subtract an epsilon here because we don't want a value that's just
    3770                 :   // slightly larger than an integer to round up to the next integer; it's
    3771                 :   // probably meant to be the integer it's close to, modulo machine precision
    3772                 :   // issues.
    3773                 :   *aRX = NSToIntCeil(aInstance.GetPrimitiveNumber(nsSVGUtils::X,
    3774                 :                                                   &mNumberPairAttributes[RADIUS],
    3775               0 :                                                   nsSVGNumberPair::eFirst) -
    3776               0 :                      MORPHOLOGY_EPSILON);
    3777                 :   *aRY = NSToIntCeil(aInstance.GetPrimitiveNumber(nsSVGUtils::Y,
    3778                 :                                                   &mNumberPairAttributes[RADIUS],
    3779               0 :                                                   nsSVGNumberPair::eSecond) -
    3780               0 :                      MORPHOLOGY_EPSILON);
    3781               0 : }
    3782                 : 
    3783                 : nsresult
    3784               0 : nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance,
    3785                 :                                  const nsTArray<const Image*>& aSources,
    3786                 :                                  const Image* aTarget,
    3787                 :                                  const nsIntRect& rect)
    3788                 : {
    3789                 :   PRInt32 rx, ry;
    3790               0 :   GetRXY(&rx, &ry, *instance);
    3791                 : 
    3792               0 :   if (rx < 0 || ry < 0) {
    3793                 :     // XXX nsSVGUtils::ReportToConsole()
    3794               0 :     return NS_OK;
    3795                 :   }
    3796               0 :   if (rx == 0 && ry == 0) {
    3797               0 :     return NS_OK;
    3798                 :   }
    3799                 : 
    3800               0 :   PRUint8* sourceData = aSources[0]->mImage->Data();
    3801               0 :   PRUint8* targetData = aTarget->mImage->Data();
    3802               0 :   PRUint32 stride = aTarget->mImage->Stride();
    3803                 :   PRUint32 xExt[4], yExt[4];  // X, Y indices of RGBA extrema
    3804                 :   PRUint8 extrema[4];         // RGBA magnitude of extrema
    3805               0 :   PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
    3806                 : 
    3807                 :   /* Scan the kernel for each pixel to determine max/min RGBA values.  Note that
    3808                 :    * as we advance in the x direction, each kernel overlaps the previous kernel.
    3809                 :    * Thus, we can avoid iterating over the entire kernel by comparing the
    3810                 :    * leading edge of the new kernel against the extrema found in the previous
    3811                 :    * kernel.   We must still scan the entire kernel if the previous extrema do
    3812                 :    * not fall within the current kernel or if we are starting a new row.
    3813                 :    */
    3814               0 :   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    3815               0 :     PRUint32 startY = NS_MAX(0, y - ry);
    3816                 :     // We need to read pixels not just in 'rect', which is limited to
    3817                 :     // the dirty part of our filter primitive subregion, but all pixels in
    3818                 :     // the given radii from the source surface, so use the surface size here.
    3819               0 :     PRUint32 endY = NS_MIN(y + ry, instance->GetSurfaceHeight() - 1);
    3820               0 :     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    3821               0 :       PRUint32 startX = NS_MAX(0, x - rx);
    3822               0 :       PRUint32 endX = NS_MIN(x + rx, instance->GetSurfaceWidth() - 1);
    3823               0 :       PRUint32 targIndex = y * stride + 4 * x;
    3824                 : 
    3825                 :       // We need to scan the entire kernel
    3826               0 :       if (x == rect.x || xExt[0]  <= startX || xExt[1] <= startX ||
    3827               0 :           xExt[2] <= startX || xExt[3] <= startX) {
    3828                 :         PRUint32 i;
    3829               0 :         for (i = 0; i < 4; i++) {
    3830               0 :           extrema[i] = sourceData[targIndex + i];
    3831                 :         }
    3832               0 :         for (PRUint32 y1 = startY; y1 <= endY; y1++) {
    3833               0 :           for (PRUint32 x1 = startX; x1 <= endX; x1++) {
    3834               0 :             for (i = 0; i < 4; i++) {
    3835               0 :               PRUint8 pixel = sourceData[y1 * stride + 4 * x1 + i];
    3836               0 :               if ((extrema[i] >= pixel &&
    3837                 :                    op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
    3838               0 :                   (extrema[i] <= pixel &&
    3839                 :                    op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
    3840               0 :                 extrema[i] = pixel;
    3841               0 :                 xExt[i] = x1;
    3842               0 :                 yExt[i] = y1;
    3843                 :               }
    3844                 :             }
    3845                 :           }
    3846               0 :         }
    3847                 :       } else { // We only need to look at the newest column
    3848               0 :         for (PRUint32 y1 = startY; y1 <= endY; y1++) {
    3849               0 :           for (PRUint32 i = 0; i < 4; i++) {
    3850               0 :             PRUint8 pixel = sourceData[y1 * stride + 4 * endX + i];
    3851               0 :             if ((extrema[i] >= pixel &&
    3852                 :                  op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
    3853               0 :                 (extrema[i] <= pixel &&
    3854                 :                  op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
    3855               0 :                 extrema[i] = pixel;
    3856               0 :                 xExt[i] = endX;
    3857               0 :                 yExt[i] = y1;
    3858                 :             }
    3859                 :           }
    3860                 :         }
    3861                 :       }
    3862               0 :       targetData[targIndex  ] = extrema[0];
    3863               0 :       targetData[targIndex+1] = extrema[1];
    3864               0 :       targetData[targIndex+2] = extrema[2];
    3865               0 :       targetData[targIndex+3] = extrema[3];
    3866                 :     }
    3867                 :   }
    3868               0 :   return NS_OK;
    3869                 : }
    3870                 : 
    3871                 : bool
    3872               0 : nsSVGFEMorphologyElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    3873                 :                                                     nsIAtom* aAttribute) const
    3874                 : {
    3875               0 :   return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    3876                 :          (aNameSpaceID == kNameSpaceID_None &&
    3877                 :           (aAttribute == nsGkAtoms::in ||
    3878                 :            aAttribute == nsGkAtoms::radius ||
    3879               0 :            aAttribute == nsGkAtoms::_operator));
    3880                 : }
    3881                 : 
    3882                 : //----------------------------------------------------------------------
    3883                 : // nsSVGElement methods
    3884                 : 
    3885                 : nsSVGElement::NumberPairAttributesInfo
    3886               0 : nsSVGFEMorphologyElement::GetNumberPairInfo()
    3887                 : {
    3888                 :   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
    3889               0 :                                   ArrayLength(sNumberPairInfo));
    3890                 : }
    3891                 : 
    3892                 : nsSVGElement::EnumAttributesInfo
    3893               0 : nsSVGFEMorphologyElement::GetEnumInfo()
    3894                 : {
    3895                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    3896               0 :                             ArrayLength(sEnumInfo));
    3897                 : }
    3898                 : 
    3899                 : nsSVGElement::StringAttributesInfo
    3900               0 : nsSVGFEMorphologyElement::GetStringInfo()
    3901                 : {
    3902                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    3903               0 :                               ArrayLength(sStringInfo));
    3904                 : }
    3905                 : 
    3906                 : //---------------------Convolve Matrix------------------------
    3907                 : 
    3908                 : typedef nsSVGFE nsSVGFEConvolveMatrixElementBase;
    3909                 : 
    3910                 : class nsSVGFEConvolveMatrixElement : public nsSVGFEConvolveMatrixElementBase,
    3911                 :                                      public nsIDOMSVGFEConvolveMatrixElement
    3912               0 : {
    3913                 :   friend nsresult NS_NewSVGFEConvolveMatrixElement(nsIContent **aResult,
    3914                 :                                                    already_AddRefed<nsINodeInfo> aNodeInfo);
    3915                 : protected:
    3916               0 :   nsSVGFEConvolveMatrixElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    3917               0 :     : nsSVGFEConvolveMatrixElementBase(aNodeInfo) {}
    3918                 : 
    3919                 : public:
    3920                 :   // interfaces:
    3921                 :   NS_DECL_ISUPPORTS_INHERITED
    3922                 : 
    3923                 :   // FE Base
    3924               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEConvolveMatrixElementBase::)
    3925                 : 
    3926                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    3927                 :                           const nsTArray<const Image*>& aSources,
    3928                 :                           const Image* aTarget,
    3929                 :                           const nsIntRect& aDataRect);
    3930                 :   virtual bool AttributeAffectsRendering(
    3931                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    3932               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    3933                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    3934                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    3935                 :           const nsSVGFilterInstance& aInstance);
    3936                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    3937                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
    3938                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    3939                 :           const nsSVGFilterInstance& aInstance);
    3940                 : 
    3941                 :   // Color Matrix
    3942                 :   NS_DECL_NSIDOMSVGFECONVOLVEMATRIXELEMENT
    3943                 : 
    3944               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEConvolveMatrixElementBase::)
    3945                 : 
    3946               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEConvolveMatrixElementBase::)
    3947               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEConvolveMatrixElementBase::)
    3948                 : 
    3949                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    3950                 : 
    3951                 :   virtual nsXPCClassInfo* GetClassInfo();
    3952                 : protected:
    3953               0 :   virtual bool OperatesOnPremultipledAlpha(PRInt32) {
    3954               0 :     return !mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
    3955                 :   }
    3956                 : 
    3957                 :   virtual NumberAttributesInfo GetNumberInfo();
    3958                 :   virtual NumberPairAttributesInfo GetNumberPairInfo();
    3959                 :   virtual IntegerAttributesInfo GetIntegerInfo();
    3960                 :   virtual IntegerPairAttributesInfo GetIntegerPairInfo();
    3961                 :   virtual BooleanAttributesInfo GetBooleanInfo();
    3962                 :   virtual EnumAttributesInfo GetEnumInfo();
    3963                 :   virtual StringAttributesInfo GetStringInfo();
    3964                 :   virtual NumberListAttributesInfo GetNumberListInfo();
    3965                 : 
    3966                 :   enum { DIVISOR, BIAS };
    3967                 :   nsSVGNumber2 mNumberAttributes[2];
    3968                 :   static NumberInfo sNumberInfo[2];
    3969                 : 
    3970                 :   enum { KERNEL_UNIT_LENGTH };
    3971                 :   nsSVGNumberPair mNumberPairAttributes[1];
    3972                 :   static NumberPairInfo sNumberPairInfo[1];
    3973                 : 
    3974                 :   enum { TARGET_X, TARGET_Y };
    3975                 :   nsSVGInteger mIntegerAttributes[2];
    3976                 :   static IntegerInfo sIntegerInfo[2];
    3977                 : 
    3978                 :   enum { ORDER };
    3979                 :   nsSVGIntegerPair mIntegerPairAttributes[1];
    3980                 :   static IntegerPairInfo sIntegerPairInfo[1];
    3981                 : 
    3982                 :   enum { PRESERVEALPHA };
    3983                 :   nsSVGBoolean mBooleanAttributes[1];
    3984                 :   static BooleanInfo sBooleanInfo[1];
    3985                 : 
    3986                 :   enum { EDGEMODE };
    3987                 :   nsSVGEnum mEnumAttributes[1];
    3988                 :   static nsSVGEnumMapping sEdgeModeMap[];
    3989                 :   static EnumInfo sEnumInfo[1];
    3990                 : 
    3991                 :   enum { RESULT, IN1 };
    3992                 :   nsSVGString mStringAttributes[2];
    3993                 :   static StringInfo sStringInfo[2];
    3994                 : 
    3995                 :   enum { KERNELMATRIX };
    3996                 :   SVGAnimatedNumberList mNumberListAttributes[1];
    3997                 :   static NumberListInfo sNumberListInfo[1];
    3998                 : };
    3999                 : 
    4000                 : nsSVGElement::NumberInfo nsSVGFEConvolveMatrixElement::sNumberInfo[2] =
    4001                 : {
    4002                 :   { &nsGkAtoms::divisor, 1, false },
    4003                 :   { &nsGkAtoms::bias, 0, false }
    4004                 : };
    4005                 : 
    4006                 : nsSVGElement::NumberPairInfo nsSVGFEConvolveMatrixElement::sNumberPairInfo[1] =
    4007                 : {
    4008                 :   { &nsGkAtoms::kernelUnitLength, 0, 0 }
    4009                 : };
    4010                 : 
    4011                 : nsSVGElement::IntegerInfo nsSVGFEConvolveMatrixElement::sIntegerInfo[2] =
    4012                 : {
    4013                 :   { &nsGkAtoms::targetX, 0 },
    4014                 :   { &nsGkAtoms::targetY, 0 }
    4015                 : };
    4016                 : 
    4017                 : nsSVGElement::IntegerPairInfo nsSVGFEConvolveMatrixElement::sIntegerPairInfo[1] =
    4018                 : {
    4019                 :   { &nsGkAtoms::order, 3, 3 }
    4020                 : };
    4021                 : 
    4022                 : nsSVGElement::BooleanInfo nsSVGFEConvolveMatrixElement::sBooleanInfo[1] =
    4023                 : {
    4024                 :   { &nsGkAtoms::preserveAlpha, false }
    4025                 : };
    4026                 : 
    4027                 : nsSVGEnumMapping nsSVGFEConvolveMatrixElement::sEdgeModeMap[] = {
    4028                 :   {&nsGkAtoms::duplicate, nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_DUPLICATE},
    4029                 :   {&nsGkAtoms::wrap, nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_WRAP},
    4030                 :   {&nsGkAtoms::none, nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_NONE},
    4031                 :   {nsnull, 0}
    4032                 : };
    4033                 : 
    4034                 : nsSVGElement::EnumInfo nsSVGFEConvolveMatrixElement::sEnumInfo[1] =
    4035                 : {
    4036                 :   { &nsGkAtoms::edgeMode,
    4037                 :     sEdgeModeMap,
    4038                 :     nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_DUPLICATE
    4039                 :   }
    4040                 : };
    4041                 : 
    4042                 : nsSVGElement::StringInfo nsSVGFEConvolveMatrixElement::sStringInfo[2] =
    4043                 : {
    4044                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    4045                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    4046                 : };
    4047                 : 
    4048                 : nsSVGElement::NumberListInfo nsSVGFEConvolveMatrixElement::sNumberListInfo[1] =
    4049                 : {
    4050                 :   { &nsGkAtoms::kernelMatrix }
    4051                 : };
    4052                 : 
    4053               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEConvolveMatrix)
    4054                 : 
    4055                 : //----------------------------------------------------------------------
    4056                 : // nsISupports methods
    4057                 : 
    4058               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEConvolveMatrixElement,nsSVGFEConvolveMatrixElementBase)
    4059               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEConvolveMatrixElement,nsSVGFEConvolveMatrixElementBase)
    4060                 : 
    4061               0 : DOMCI_NODE_DATA(SVGFEConvolveMatrixElement, nsSVGFEConvolveMatrixElement)
    4062                 : 
    4063               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEConvolveMatrixElement)
    4064               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEConvolveMatrixElement, nsIDOMNode,
    4065                 :                            nsIDOMElement, nsIDOMSVGElement,
    4066                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    4067                 :                            nsIDOMSVGFEConvolveMatrixElement)
    4068               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEConvolveMatrixElement)
    4069               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEConvolveMatrixElementBase)
    4070                 : 
    4071                 : 
    4072                 : //----------------------------------------------------------------------
    4073                 : // nsIDOMNode methods
    4074                 : 
    4075               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEConvolveMatrixElement)
    4076                 : 
    4077                 : //----------------------------------------------------------------------
    4078                 : // nsSVGFEConvolveMatrixElement methods
    4079                 : 
    4080               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    4081                 : {
    4082               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    4083                 : }
    4084                 : 
    4085               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetOrderX(nsIDOMSVGAnimatedInteger * *aOrderX)
    4086                 : {
    4087               0 :   return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(aOrderX, nsSVGIntegerPair::eFirst, this);
    4088                 : }
    4089                 : 
    4090               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetOrderY(nsIDOMSVGAnimatedInteger * *aOrderY)
    4091                 : {
    4092               0 :   return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(aOrderY, nsSVGIntegerPair::eSecond, this);
    4093                 : }
    4094                 : 
    4095               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetKernelMatrix(nsIDOMSVGAnimatedNumberList * *aKernelMatrix)
    4096                 : {
    4097                 :   *aKernelMatrix = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX],
    4098               0 :                                                            this, KERNELMATRIX).get();
    4099               0 :   return NS_OK;
    4100                 : }
    4101                 : 
    4102               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetTargetX(nsIDOMSVGAnimatedInteger * *aTargetX)
    4103                 : {
    4104               0 :   return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(aTargetX, this);
    4105                 : }
    4106                 : 
    4107               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetTargetY(nsIDOMSVGAnimatedInteger * *aTargetY)
    4108                 : {
    4109               0 :   return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(aTargetY, this);
    4110                 : }
    4111                 : 
    4112               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetEdgeMode(nsIDOMSVGAnimatedEnumeration * *aEdgeMode)
    4113                 : {
    4114               0 :   return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(aEdgeMode, this);
    4115                 : }
    4116                 : 
    4117               0 : NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetPreserveAlpha(nsIDOMSVGAnimatedBoolean * *aPreserveAlpha)
    4118                 : {
    4119               0 :   return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(aPreserveAlpha, this);
    4120                 : }
    4121                 : 
    4122                 : NS_IMETHODIMP
    4123               0 : nsSVGFEConvolveMatrixElement::GetDivisor(nsIDOMSVGAnimatedNumber **aDivisor)
    4124                 : {
    4125               0 :   return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(aDivisor, this);
    4126                 : }
    4127                 : 
    4128                 : NS_IMETHODIMP
    4129               0 : nsSVGFEConvolveMatrixElement::GetBias(nsIDOMSVGAnimatedNumber **aBias)
    4130                 : {
    4131               0 :   return mNumberAttributes[BIAS].ToDOMAnimatedNumber(aBias, this);
    4132                 : }
    4133                 : 
    4134                 : NS_IMETHODIMP
    4135               0 : nsSVGFEConvolveMatrixElement::GetKernelUnitLengthX(nsIDOMSVGAnimatedNumber **aKernelX)
    4136                 : {
    4137                 :   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelX,
    4138                 :                                                                        nsSVGNumberPair::eFirst,
    4139               0 :                                                                        this);
    4140                 : }
    4141                 : 
    4142                 : NS_IMETHODIMP
    4143               0 : nsSVGFEConvolveMatrixElement::GetKernelUnitLengthY(nsIDOMSVGAnimatedNumber **aKernelY)
    4144                 : {
    4145                 :   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelY,
    4146                 :                                                                        nsSVGNumberPair::eSecond,
    4147               0 :                                                                        this);
    4148                 : }
    4149                 : 
    4150                 : void
    4151               0 : nsSVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    4152                 : {
    4153               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    4154               0 : }
    4155                 : 
    4156                 : nsIntRect
    4157               0 : nsSVGFEConvolveMatrixElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    4158                 :         const nsSVGFilterInstance& aInstance)
    4159                 : {
    4160                 :   // XXX A more precise box is possible when 'bias' is zero and 'edgeMode' is
    4161                 :   // 'none', but it requires analysis of 'kernelUnitLength', 'order' and
    4162                 :   // 'targetX/Y', so it's quite a lot of work. Don't do it for now.
    4163               0 :   return GetMaxRect();
    4164                 : }
    4165                 : 
    4166                 : void
    4167               0 : nsSVGFEConvolveMatrixElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    4168                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
    4169                 : {
    4170                 :   // XXX Precise results are possible but we're going to skip that work
    4171                 :   // for now. Do nothing, which means the needed-box remains the
    4172                 :   // source's output bounding box.
    4173               0 : }
    4174                 : 
    4175                 : nsIntRect
    4176               0 : nsSVGFEConvolveMatrixElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    4177                 :                                                 const nsSVGFilterInstance& aInstance)
    4178                 : {
    4179                 :   // XXX Precise results are possible but we're going to skip that work
    4180                 :   // for now.
    4181               0 :   return GetMaxRect();
    4182                 : }
    4183                 : 
    4184               0 : static PRInt32 BoundInterval(PRInt32 aVal, PRInt32 aMax)
    4185                 : {
    4186               0 :   aVal = NS_MAX(aVal, 0);
    4187               0 :   return NS_MIN(aVal, aMax - 1);
    4188                 : }
    4189                 : 
    4190                 : static void
    4191               0 : ConvolvePixel(const PRUint8 *aSourceData,
    4192                 :               PRUint8 *aTargetData,
    4193                 :               PRInt32 aWidth, PRInt32 aHeight,
    4194                 :               PRInt32 aStride,
    4195                 :               PRInt32 aX, PRInt32 aY,
    4196                 :               PRUint16 aEdgeMode,
    4197                 :               const float *aKernel,
    4198                 :               float aDivisor, float aBias,
    4199                 :               bool aPreserveAlpha,
    4200                 :               PRInt32 aOrderX, PRInt32 aOrderY,
    4201                 :               PRInt32 aTargetX, PRInt32 aTargetY)
    4202                 : {
    4203               0 :   float sum[4] = {0, 0, 0, 0};
    4204               0 :   aBias *= 255;
    4205                 :   PRInt32 offsets[4] = {GFX_ARGB32_OFFSET_R,
    4206                 :                         GFX_ARGB32_OFFSET_G,
    4207                 :                         GFX_ARGB32_OFFSET_B,
    4208               0 :                         GFX_ARGB32_OFFSET_A } ;
    4209               0 :   PRInt32 channels = aPreserveAlpha ? 3 : 4;
    4210                 : 
    4211               0 :   for (PRInt32 y = 0; y < aOrderY; y++) {
    4212               0 :     PRInt32 sampleY = aY + y - aTargetY;
    4213               0 :     bool overscanY = sampleY < 0 || sampleY >= aHeight;
    4214               0 :     for (PRInt32 x = 0; x < aOrderX; x++) {
    4215               0 :       PRInt32 sampleX = aX + x - aTargetX;
    4216               0 :       bool overscanX = sampleX < 0 || sampleX >= aWidth;
    4217               0 :       for (PRInt32 i = 0; i < channels; i++) {
    4218               0 :         if (overscanY || overscanX) {
    4219               0 :           switch (aEdgeMode) {
    4220                 :             case nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_DUPLICATE:
    4221                 :               sum[i] +=
    4222               0 :                 aSourceData[BoundInterval(sampleY, aHeight) * aStride +
    4223               0 :                             BoundInterval(sampleX, aWidth) * 4 + offsets[i]] *
    4224               0 :                 aKernel[aOrderX * y + x];
    4225               0 :               break;
    4226                 :             case nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_WRAP:
    4227                 :               sum[i] +=
    4228               0 :                 aSourceData[WrapInterval(sampleY, aHeight) * aStride +
    4229               0 :                             WrapInterval(sampleX, aWidth) * 4 + offsets[i]] *
    4230               0 :                 aKernel[aOrderX * y + x];
    4231               0 :               break;
    4232                 :             default:
    4233               0 :               break;
    4234                 :           }
    4235                 :         } else {
    4236                 :           sum[i] +=
    4237               0 :             aSourceData[sampleY * aStride + 4 * sampleX + offsets[i]] *
    4238               0 :             aKernel[aOrderX * y + x];
    4239                 :         }
    4240                 :       }
    4241                 :     }
    4242                 :   }
    4243               0 :   for (PRInt32 i = 0; i < channels; i++) {
    4244               0 :     aTargetData[aY * aStride + 4 * aX + offsets[i]] =
    4245               0 :       BoundInterval(static_cast<PRInt32>(sum[i] / aDivisor + aBias), 256);
    4246                 :   }
    4247               0 :   if (aPreserveAlpha) {
    4248               0 :     aTargetData[aY * aStride + 4 * aX + GFX_ARGB32_OFFSET_A] =
    4249               0 :       aSourceData[aY * aStride + 4 * aX + GFX_ARGB32_OFFSET_A];
    4250                 :   }
    4251               0 : }
    4252                 : 
    4253                 : nsresult
    4254               0 : nsSVGFEConvolveMatrixElement::Filter(nsSVGFilterInstance *instance,
    4255                 :                                      const nsTArray<const Image*>& aSources,
    4256                 :                                      const Image* aTarget,
    4257                 :                                      const nsIntRect& rect)
    4258                 : {
    4259                 :   const SVGNumberList &kernelMatrix =
    4260               0 :     mNumberListAttributes[KERNELMATRIX].GetAnimValue();
    4261               0 :   PRUint32 kmLength = kernelMatrix.Length();
    4262                 : 
    4263               0 :   PRInt32 orderX = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eFirst);
    4264               0 :   PRInt32 orderY = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eSecond);
    4265                 : 
    4266               0 :   if (orderX <= 0 || orderY <= 0 ||
    4267                 :       static_cast<PRUint32>(orderX * orderY) != kmLength) {
    4268               0 :     return NS_ERROR_FAILURE;
    4269                 :   }
    4270                 : 
    4271                 :   PRInt32 targetX, targetY;
    4272               0 :   GetAnimatedIntegerValues(&targetX, &targetY, nsnull);
    4273                 : 
    4274               0 :   if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) {
    4275               0 :     if (targetX < 0 || targetX >= orderX)
    4276               0 :       return NS_ERROR_FAILURE;
    4277                 :   } else {
    4278               0 :     targetX = orderX / 2;
    4279                 :   }
    4280               0 :   if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) {
    4281               0 :     if (targetY < 0 || targetY >= orderY)
    4282               0 :       return NS_ERROR_FAILURE;
    4283                 :   } else {
    4284               0 :     targetY = orderY / 2;
    4285                 :   }
    4286                 : 
    4287               0 :   if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION ||
    4288                 :       orderY > NS_SVG_OFFSCREEN_MAX_DIMENSION)
    4289               0 :     return NS_ERROR_FAILURE;
    4290               0 :   nsAutoArrayPtr<float> kernel(new float[orderX * orderY]);
    4291               0 :   if (!kernel)
    4292               0 :     return NS_ERROR_FAILURE;
    4293               0 :   for (PRUint32 i = 0; i < kmLength; i++) {
    4294               0 :     kernel[kmLength - 1 - i] = kernelMatrix[i];
    4295                 :   }
    4296                 : 
    4297                 :   float divisor;
    4298               0 :   if (mNumberAttributes[DIVISOR].IsExplicitlySet()) {
    4299               0 :     divisor = mNumberAttributes[DIVISOR].GetAnimValue();
    4300               0 :     if (divisor == 0)
    4301               0 :       return NS_ERROR_FAILURE;
    4302                 :   } else {
    4303               0 :     divisor = kernel[0];
    4304               0 :     for (PRUint32 i = 1; i < kmLength; i++)
    4305               0 :       divisor += kernel[i];
    4306               0 :     if (divisor == 0)
    4307               0 :       divisor = 1;
    4308                 :   }
    4309                 : 
    4310               0 :   ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect,
    4311               0 :                                       &mNumberPairAttributes[KERNEL_UNIT_LENGTH]);
    4312               0 :   if (!info.mTarget)
    4313               0 :     return NS_ERROR_FAILURE;
    4314                 : 
    4315               0 :   PRUint16 edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue();
    4316               0 :   bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
    4317                 : 
    4318               0 :   float bias = mNumberAttributes[BIAS].GetAnimValue();
    4319                 : 
    4320               0 :   const nsIntRect& dataRect = info.mDataRect;
    4321               0 :   PRInt32 stride = info.mSource->Stride();
    4322               0 :   PRInt32 width = info.mSource->GetSize().width;
    4323               0 :   PRInt32 height = info.mSource->GetSize().height;
    4324               0 :   PRUint8 *sourceData = info.mSource->Data();
    4325               0 :   PRUint8 *targetData = info.mTarget->Data();
    4326                 : 
    4327               0 :   for (PRInt32 y = dataRect.y; y < dataRect.YMost(); y++) {
    4328               0 :     for (PRInt32 x = dataRect.x; x < dataRect.XMost(); x++) {
    4329                 :       ConvolvePixel(sourceData, targetData,
    4330                 :                     width, height, stride,
    4331                 :                     x, y,
    4332                 :                     edgeMode, kernel, divisor, bias, preserveAlpha,
    4333               0 :                     orderX, orderY, targetX, targetY);
    4334                 :     }
    4335                 :   }
    4336                 : 
    4337               0 :   FinishScalingFilter(&info);
    4338                 : 
    4339               0 :   return NS_OK;
    4340                 : }
    4341                 : 
    4342                 : bool
    4343               0 : nsSVGFEConvolveMatrixElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    4344                 :                                                         nsIAtom* aAttribute) const
    4345                 : {
    4346               0 :   return nsSVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    4347                 :          (aNameSpaceID == kNameSpaceID_None &&
    4348                 :           (aAttribute == nsGkAtoms::in ||
    4349                 :            aAttribute == nsGkAtoms::divisor ||
    4350                 :            aAttribute == nsGkAtoms::bias ||
    4351                 :            aAttribute == nsGkAtoms::kernelUnitLength ||
    4352                 :            aAttribute == nsGkAtoms::targetX ||
    4353                 :            aAttribute == nsGkAtoms::targetY ||
    4354                 :            aAttribute == nsGkAtoms::order ||
    4355                 :            aAttribute == nsGkAtoms::preserveAlpha||
    4356                 :            aAttribute == nsGkAtoms::edgeMode ||
    4357               0 :            aAttribute == nsGkAtoms::kernelMatrix));
    4358                 : }
    4359                 : 
    4360                 : //----------------------------------------------------------------------
    4361                 : // nsSVGElement methods
    4362                 : 
    4363                 : nsSVGElement::NumberAttributesInfo
    4364               0 : nsSVGFEConvolveMatrixElement::GetNumberInfo()
    4365                 : {
    4366                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    4367               0 :                               ArrayLength(sNumberInfo));
    4368                 : }
    4369                 : 
    4370                 : nsSVGElement::NumberPairAttributesInfo
    4371               0 : nsSVGFEConvolveMatrixElement::GetNumberPairInfo()
    4372                 : {
    4373                 :   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
    4374               0 :                                   ArrayLength(sNumberPairInfo));
    4375                 : }
    4376                 : 
    4377                 : nsSVGElement::IntegerAttributesInfo
    4378               0 : nsSVGFEConvolveMatrixElement::GetIntegerInfo()
    4379                 : {
    4380                 :   return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
    4381               0 :                                ArrayLength(sIntegerInfo));
    4382                 : }
    4383                 : 
    4384                 : nsSVGElement::IntegerPairAttributesInfo
    4385               0 : nsSVGFEConvolveMatrixElement::GetIntegerPairInfo()
    4386                 : {
    4387                 :   return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo,
    4388               0 :                                    ArrayLength(sIntegerPairInfo));
    4389                 : }
    4390                 : 
    4391                 : nsSVGElement::BooleanAttributesInfo
    4392               0 : nsSVGFEConvolveMatrixElement::GetBooleanInfo()
    4393                 : {
    4394                 :   return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo,
    4395               0 :                                ArrayLength(sBooleanInfo));
    4396                 : }
    4397                 : 
    4398                 : nsSVGElement::EnumAttributesInfo
    4399               0 : nsSVGFEConvolveMatrixElement::GetEnumInfo()
    4400                 : {
    4401                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    4402               0 :                             ArrayLength(sEnumInfo));
    4403                 : }
    4404                 : 
    4405                 : nsSVGElement::StringAttributesInfo
    4406               0 : nsSVGFEConvolveMatrixElement::GetStringInfo()
    4407                 : {
    4408                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    4409               0 :                               ArrayLength(sStringInfo));
    4410                 : }
    4411                 : 
    4412                 : nsSVGElement::NumberListAttributesInfo
    4413               0 : nsSVGFEConvolveMatrixElement::GetNumberListInfo()
    4414                 : {
    4415                 :   return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
    4416               0 :                                   ArrayLength(sNumberListInfo));
    4417                 : }
    4418                 : 
    4419                 : //---------------------DistantLight------------------------
    4420                 : 
    4421                 : typedef SVGFEUnstyledElement nsSVGFEDistantLightElementBase;
    4422                 : 
    4423                 : class nsSVGFEDistantLightElement : public nsSVGFEDistantLightElementBase,
    4424                 :                                    public nsIDOMSVGFEDistantLightElement
    4425               0 : {
    4426                 :   friend nsresult NS_NewSVGFEDistantLightElement(nsIContent **aResult,
    4427                 :                                                  already_AddRefed<nsINodeInfo> aNodeInfo);
    4428                 : protected:
    4429               0 :   nsSVGFEDistantLightElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    4430               0 :     : nsSVGFEDistantLightElementBase(aNodeInfo) {}
    4431                 : 
    4432                 : public:
    4433                 :   // interfaces:
    4434                 :   NS_DECL_ISUPPORTS_INHERITED
    4435                 :   NS_DECL_NSIDOMSVGFEDISTANTLIGHTELEMENT
    4436                 : 
    4437               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEDistantLightElementBase::)
    4438               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEDistantLightElementBase::)
    4439               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEDistantLightElementBase::)
    4440                 : 
    4441                 :   virtual bool AttributeAffectsRendering(
    4442                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    4443                 : 
    4444                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    4445                 : 
    4446                 :   virtual nsXPCClassInfo* GetClassInfo();
    4447                 : protected:
    4448                 :   virtual NumberAttributesInfo GetNumberInfo();
    4449                 : 
    4450                 :   enum { AZIMUTH, ELEVATION };
    4451                 :   nsSVGNumber2 mNumberAttributes[2];
    4452                 :   static NumberInfo sNumberInfo[2];
    4453                 : };
    4454                 : 
    4455               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEDistantLight)
    4456                 : 
    4457                 : nsSVGElement::NumberInfo nsSVGFEDistantLightElement::sNumberInfo[2] =
    4458                 : {
    4459                 :   { &nsGkAtoms::azimuth,   0, false },
    4460                 :   { &nsGkAtoms::elevation, 0, false }
    4461                 : };
    4462                 : 
    4463                 : //----------------------------------------------------------------------
    4464                 : // nsISupports methods
    4465                 : 
    4466               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEDistantLightElement,nsSVGFEDistantLightElementBase)
    4467               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEDistantLightElement,nsSVGFEDistantLightElementBase)
    4468                 : 
    4469               0 : DOMCI_NODE_DATA(SVGFEDistantLightElement, nsSVGFEDistantLightElement)
    4470                 : 
    4471               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEDistantLightElement)
    4472               0 :   NS_NODE_INTERFACE_TABLE4(nsSVGFEDistantLightElement, nsIDOMNode,
    4473                 :                            nsIDOMElement, nsIDOMSVGElement,
    4474                 :                            nsIDOMSVGFEDistantLightElement)
    4475               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEDistantLightElement)
    4476               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEDistantLightElementBase)
    4477                 : 
    4478                 : //----------------------------------------------------------------------
    4479                 : // nsIDOMNode methods
    4480                 : 
    4481               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEDistantLightElement)
    4482                 : 
    4483                 : //----------------------------------------------------------------------
    4484                 : // nsFEUnstyledElement methods
    4485                 : 
    4486                 : bool
    4487               0 : nsSVGFEDistantLightElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    4488                 :                                                       nsIAtom* aAttribute) const
    4489                 : {
    4490                 :   return aNameSpaceID == kNameSpaceID_None &&
    4491                 :          (aAttribute == nsGkAtoms::azimuth ||
    4492               0 :           aAttribute == nsGkAtoms::elevation);
    4493                 : }
    4494                 : 
    4495                 : //----------------------------------------------------------------------
    4496                 : // nsIDOMSVGFEDistantLightElement methods
    4497                 : 
    4498                 : NS_IMETHODIMP
    4499               0 : nsSVGFEDistantLightElement::GetAzimuth(nsIDOMSVGAnimatedNumber **aAzimuth)
    4500                 : {
    4501                 :   return mNumberAttributes[AZIMUTH].ToDOMAnimatedNumber(aAzimuth,
    4502               0 :                                                         this);
    4503                 : }
    4504                 : 
    4505                 : NS_IMETHODIMP
    4506               0 : nsSVGFEDistantLightElement::GetElevation(nsIDOMSVGAnimatedNumber **aElevation)
    4507                 : {
    4508                 :   return mNumberAttributes[ELEVATION].ToDOMAnimatedNumber(aElevation,
    4509               0 :                                                           this);
    4510                 : }
    4511                 : 
    4512                 : //----------------------------------------------------------------------
    4513                 : // nsSVGElement methods
    4514                 : 
    4515                 : nsSVGElement::NumberAttributesInfo
    4516               0 : nsSVGFEDistantLightElement::GetNumberInfo()
    4517                 : {
    4518                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    4519               0 :                               ArrayLength(sNumberInfo));
    4520                 : }
    4521                 : 
    4522                 : //---------------------PointLight------------------------
    4523                 : 
    4524                 : typedef SVGFEUnstyledElement nsSVGFEPointLightElementBase;
    4525                 : 
    4526                 : class nsSVGFEPointLightElement : public nsSVGFEPointLightElementBase,
    4527                 :                                  public nsIDOMSVGFEPointLightElement
    4528               0 : {
    4529                 :   friend nsresult NS_NewSVGFEPointLightElement(nsIContent **aResult,
    4530                 :                                                  already_AddRefed<nsINodeInfo> aNodeInfo);
    4531                 : protected:
    4532               0 :   nsSVGFEPointLightElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    4533               0 :     : nsSVGFEPointLightElementBase(aNodeInfo) {}
    4534                 : 
    4535                 : public:
    4536                 :   // interfaces:
    4537                 :   NS_DECL_ISUPPORTS_INHERITED
    4538                 :   NS_DECL_NSIDOMSVGFEPOINTLIGHTELEMENT
    4539                 : 
    4540               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEPointLightElementBase::)
    4541               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEPointLightElementBase::)
    4542               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEPointLightElementBase::)
    4543                 : 
    4544                 :   virtual bool AttributeAffectsRendering(
    4545                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    4546                 : 
    4547                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    4548                 : 
    4549                 :   virtual nsXPCClassInfo* GetClassInfo();
    4550                 : protected:
    4551                 :   virtual NumberAttributesInfo GetNumberInfo();
    4552                 : 
    4553                 :   enum { X, Y, Z };
    4554                 :   nsSVGNumber2 mNumberAttributes[3];
    4555                 :   static NumberInfo sNumberInfo[3];
    4556                 : };
    4557                 : 
    4558               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEPointLight)
    4559                 : 
    4560                 : nsSVGElement::NumberInfo nsSVGFEPointLightElement::sNumberInfo[3] =
    4561                 : {
    4562                 :   { &nsGkAtoms::x, 0, false },
    4563                 :   { &nsGkAtoms::y, 0, false },
    4564                 :   { &nsGkAtoms::z, 0, false }
    4565                 : };
    4566                 : 
    4567                 : //----------------------------------------------------------------------
    4568                 : // nsISupports methods
    4569                 : 
    4570               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEPointLightElement,nsSVGFEPointLightElementBase)
    4571               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEPointLightElement,nsSVGFEPointLightElementBase)
    4572                 : 
    4573               0 : DOMCI_NODE_DATA(SVGFEPointLightElement, nsSVGFEPointLightElement)
    4574                 : 
    4575               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEPointLightElement)
    4576               0 :   NS_NODE_INTERFACE_TABLE4(nsSVGFEPointLightElement, nsIDOMNode,
    4577                 :                            nsIDOMElement, nsIDOMSVGElement,
    4578                 :                            nsIDOMSVGFEPointLightElement)
    4579               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEPointLightElement)
    4580               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEPointLightElementBase)
    4581                 : 
    4582                 : //----------------------------------------------------------------------
    4583                 : // nsIDOMNode methods
    4584                 : 
    4585               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEPointLightElement)
    4586                 : 
    4587                 : //----------------------------------------------------------------------
    4588                 : // nsFEUnstyledElement methods
    4589                 : 
    4590                 : bool
    4591               0 : nsSVGFEPointLightElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    4592                 :                                                     nsIAtom* aAttribute) const
    4593                 : {
    4594                 :   return aNameSpaceID == kNameSpaceID_None &&
    4595                 :          (aAttribute == nsGkAtoms::x ||
    4596                 :           aAttribute == nsGkAtoms::y ||
    4597               0 :           aAttribute == nsGkAtoms::z);
    4598                 : }
    4599                 : 
    4600                 : //----------------------------------------------------------------------
    4601                 : // nsIDOMSVGFEPointLightElement methods
    4602                 : 
    4603                 : NS_IMETHODIMP
    4604               0 : nsSVGFEPointLightElement::GetX(nsIDOMSVGAnimatedNumber **aX)
    4605                 : {
    4606               0 :   return mNumberAttributes[X].ToDOMAnimatedNumber(aX, this);
    4607                 : }
    4608                 : 
    4609                 : NS_IMETHODIMP
    4610               0 : nsSVGFEPointLightElement::GetY(nsIDOMSVGAnimatedNumber **aY)
    4611                 : {
    4612               0 :   return mNumberAttributes[Y].ToDOMAnimatedNumber(aY, this);
    4613                 : }
    4614                 : 
    4615                 : NS_IMETHODIMP
    4616               0 : nsSVGFEPointLightElement::GetZ(nsIDOMSVGAnimatedNumber **aZ)
    4617                 : {
    4618               0 :   return mNumberAttributes[Z].ToDOMAnimatedNumber(aZ, this);
    4619                 : }
    4620                 : 
    4621                 : //----------------------------------------------------------------------
    4622                 : // nsSVGElement methods
    4623                 : 
    4624                 : nsSVGElement::NumberAttributesInfo
    4625               0 : nsSVGFEPointLightElement::GetNumberInfo()
    4626                 : {
    4627                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    4628               0 :                               ArrayLength(sNumberInfo));
    4629                 : }
    4630                 : 
    4631                 : //---------------------SpotLight------------------------
    4632                 : 
    4633                 : typedef SVGFEUnstyledElement nsSVGFESpotLightElementBase;
    4634                 : 
    4635                 : class nsSVGFESpotLightElement : public nsSVGFESpotLightElementBase,
    4636                 :                                 public nsIDOMSVGFESpotLightElement
    4637               0 : {
    4638                 :   friend nsresult NS_NewSVGFESpotLightElement(nsIContent **aResult,
    4639                 :                                               already_AddRefed<nsINodeInfo> aNodeInfo);
    4640                 :   friend class nsSVGFELightingElement;
    4641                 : protected:
    4642               0 :   nsSVGFESpotLightElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    4643               0 :     : nsSVGFESpotLightElementBase(aNodeInfo) {}
    4644                 : 
    4645                 : public:
    4646                 :   // interfaces:
    4647                 :   NS_DECL_ISUPPORTS_INHERITED
    4648                 :   NS_DECL_NSIDOMSVGFESPOTLIGHTELEMENT
    4649                 : 
    4650               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFESpotLightElementBase::)
    4651               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFESpotLightElementBase::)
    4652               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFESpotLightElementBase::)
    4653                 : 
    4654                 :   virtual bool AttributeAffectsRendering(
    4655                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    4656                 : 
    4657                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    4658                 : 
    4659                 :   virtual nsXPCClassInfo* GetClassInfo();
    4660                 : protected:
    4661                 :   virtual NumberAttributesInfo GetNumberInfo();
    4662                 : 
    4663                 :   enum { X, Y, Z, POINTS_AT_X, POINTS_AT_Y, POINTS_AT_Z,
    4664                 :          SPECULAR_EXPONENT, LIMITING_CONE_ANGLE };
    4665                 :   nsSVGNumber2 mNumberAttributes[8];
    4666                 :   static NumberInfo sNumberInfo[8];
    4667                 : };
    4668                 : 
    4669               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FESpotLight)
    4670                 : 
    4671                 : nsSVGElement::NumberInfo nsSVGFESpotLightElement::sNumberInfo[8] =
    4672                 : {
    4673                 :   { &nsGkAtoms::x, 0, false },
    4674                 :   { &nsGkAtoms::y, 0, false },
    4675                 :   { &nsGkAtoms::z, 0, false },
    4676                 :   { &nsGkAtoms::pointsAtX, 0, false },
    4677                 :   { &nsGkAtoms::pointsAtY, 0, false },
    4678                 :   { &nsGkAtoms::pointsAtZ, 0, false },
    4679                 :   { &nsGkAtoms::specularExponent, 1, false },
    4680                 :   { &nsGkAtoms::limitingConeAngle, 0, false }
    4681                 : };
    4682                 : 
    4683                 : //----------------------------------------------------------------------
    4684                 : // nsISupports methods
    4685                 : 
    4686               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFESpotLightElement,nsSVGFESpotLightElementBase)
    4687               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFESpotLightElement,nsSVGFESpotLightElementBase)
    4688                 : 
    4689               0 : DOMCI_NODE_DATA(SVGFESpotLightElement, nsSVGFESpotLightElement)
    4690                 : 
    4691               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFESpotLightElement)
    4692               0 :   NS_NODE_INTERFACE_TABLE4(nsSVGFESpotLightElement, nsIDOMNode,
    4693                 :                            nsIDOMElement, nsIDOMSVGElement,
    4694                 :                            nsIDOMSVGFESpotLightElement)
    4695               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFESpotLightElement)
    4696               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFESpotLightElementBase)
    4697                 : 
    4698                 : //----------------------------------------------------------------------
    4699                 : // nsIDOMNode methods
    4700                 : 
    4701               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFESpotLightElement)
    4702                 : 
    4703                 : //----------------------------------------------------------------------
    4704                 : // nsFEUnstyledElement methods
    4705                 : 
    4706                 : bool
    4707               0 : nsSVGFESpotLightElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    4708                 :                                                    nsIAtom* aAttribute) const
    4709                 : {
    4710                 :   return aNameSpaceID == kNameSpaceID_None &&
    4711                 :          (aAttribute == nsGkAtoms::x ||
    4712                 :           aAttribute == nsGkAtoms::y ||
    4713                 :           aAttribute == nsGkAtoms::z ||
    4714                 :           aAttribute == nsGkAtoms::pointsAtX ||
    4715                 :           aAttribute == nsGkAtoms::pointsAtY ||
    4716                 :           aAttribute == nsGkAtoms::pointsAtZ ||
    4717                 :           aAttribute == nsGkAtoms::specularExponent ||
    4718               0 :           aAttribute == nsGkAtoms::limitingConeAngle);
    4719                 : }
    4720                 : 
    4721                 : //----------------------------------------------------------------------
    4722                 : // nsIDOMSVGFESpotLightElement methods
    4723                 : 
    4724                 : NS_IMETHODIMP
    4725               0 : nsSVGFESpotLightElement::GetX(nsIDOMSVGAnimatedNumber **aX)
    4726                 : {
    4727               0 :   return mNumberAttributes[X].ToDOMAnimatedNumber(aX, this);
    4728                 : }
    4729                 : 
    4730                 : NS_IMETHODIMP
    4731               0 : nsSVGFESpotLightElement::GetY(nsIDOMSVGAnimatedNumber **aY)
    4732                 : {
    4733               0 :   return mNumberAttributes[Y].ToDOMAnimatedNumber(aY, this);
    4734                 : }
    4735                 : 
    4736                 : NS_IMETHODIMP
    4737               0 : nsSVGFESpotLightElement::GetZ(nsIDOMSVGAnimatedNumber **aZ)
    4738                 : {
    4739               0 :   return mNumberAttributes[Z].ToDOMAnimatedNumber(aZ, this);
    4740                 : }
    4741                 : 
    4742                 : NS_IMETHODIMP
    4743               0 : nsSVGFESpotLightElement::GetPointsAtX(nsIDOMSVGAnimatedNumber **aX)
    4744                 : {
    4745               0 :   return mNumberAttributes[POINTS_AT_X].ToDOMAnimatedNumber(aX, this);
    4746                 : }
    4747                 : 
    4748                 : NS_IMETHODIMP
    4749               0 : nsSVGFESpotLightElement::GetPointsAtY(nsIDOMSVGAnimatedNumber **aY)
    4750                 : {
    4751               0 :   return mNumberAttributes[POINTS_AT_Y].ToDOMAnimatedNumber(aY, this);
    4752                 : }
    4753                 : 
    4754                 : NS_IMETHODIMP
    4755               0 : nsSVGFESpotLightElement::GetPointsAtZ(nsIDOMSVGAnimatedNumber **aZ)
    4756                 : {
    4757               0 :   return mNumberAttributes[POINTS_AT_Z].ToDOMAnimatedNumber(aZ, this);
    4758                 : }
    4759                 : 
    4760                 : NS_IMETHODIMP
    4761               0 : nsSVGFESpotLightElement::GetSpecularExponent(nsIDOMSVGAnimatedNumber **aExponent)
    4762                 : {
    4763                 :   return mNumberAttributes[SPECULAR_EXPONENT].ToDOMAnimatedNumber(aExponent,
    4764               0 :                                                                   this);
    4765                 : }
    4766                 : 
    4767                 : NS_IMETHODIMP
    4768               0 : nsSVGFESpotLightElement::GetLimitingConeAngle(nsIDOMSVGAnimatedNumber **aAngle)
    4769                 : {
    4770                 :   return mNumberAttributes[LIMITING_CONE_ANGLE].ToDOMAnimatedNumber(aAngle,
    4771               0 :                                                                     this);
    4772                 : }
    4773                 : 
    4774                 : //----------------------------------------------------------------------
    4775                 : // nsSVGElement methods
    4776                 : 
    4777                 : nsSVGElement::NumberAttributesInfo
    4778               0 : nsSVGFESpotLightElement::GetNumberInfo()
    4779                 : {
    4780                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    4781               0 :                               ArrayLength(sNumberInfo));
    4782                 : }
    4783                 : 
    4784                 : //------------------------------------------------------------
    4785                 : 
    4786                 : typedef nsSVGFE nsSVGFELightingElementBase;
    4787                 : 
    4788                 : class nsSVGFELightingElement : public nsSVGFELightingElementBase
    4789               0 : {
    4790                 : protected:
    4791               0 :   nsSVGFELightingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    4792               0 :     : nsSVGFELightingElementBase(aNodeInfo) {}
    4793                 : 
    4794                 : public:
    4795                 :   // interfaces:
    4796                 :   NS_DECL_ISUPPORTS_INHERITED
    4797                 : 
    4798                 :   // FE Base
    4799               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFELightingElementBase::)
    4800                 : 
    4801                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    4802                 :                           const nsTArray<const Image*>& aSources,
    4803                 :                           const Image* aTarget,
    4804                 :                           const nsIntRect& aDataRect);
    4805                 :   virtual bool AttributeAffectsRendering(
    4806                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    4807               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    4808                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    4809                 :   // XXX shouldn't we have ComputeTargetBBox here, since the output can
    4810                 :   // extend beyond the bounds of the inputs thanks to the convolution kernel?
    4811                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    4812                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
    4813                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    4814                 :           const nsSVGFilterInstance& aInstance);
    4815                 : 
    4816               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFELightingElementBase::)
    4817               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFELightingElementBase::)
    4818               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFELightingElementBase::)
    4819                 : 
    4820                 :   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
    4821                 : 
    4822                 : protected:
    4823                 :   virtual void
    4824                 :   LightPixel(const float *N, const float *L,
    4825                 :              nscolor color, PRUint8 *targetData) = 0;
    4826                 : 
    4827                 :   virtual NumberAttributesInfo GetNumberInfo();
    4828                 :   virtual NumberPairAttributesInfo GetNumberPairInfo();
    4829                 :   virtual StringAttributesInfo GetStringInfo();
    4830                 : 
    4831                 :   enum { SURFACE_SCALE, DIFFUSE_CONSTANT, SPECULAR_CONSTANT, SPECULAR_EXPONENT };
    4832                 :   nsSVGNumber2 mNumberAttributes[4];
    4833                 :   static NumberInfo sNumberInfo[4];
    4834                 : 
    4835                 :   enum { KERNEL_UNIT_LENGTH };
    4836                 :   nsSVGNumberPair mNumberPairAttributes[1];
    4837                 :   static NumberPairInfo sNumberPairInfo[1];
    4838                 : 
    4839                 :   enum { RESULT, IN1 };
    4840                 :   nsSVGString mStringAttributes[2];
    4841                 :   static StringInfo sStringInfo[2];
    4842                 : };
    4843                 : 
    4844                 : nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] =
    4845                 : {
    4846                 :   { &nsGkAtoms::surfaceScale, 1, false },
    4847                 :   { &nsGkAtoms::diffuseConstant, 1, false },
    4848                 :   { &nsGkAtoms::specularConstant, 1, false },
    4849                 :   { &nsGkAtoms::specularExponent, 1, false }
    4850                 : };
    4851                 : 
    4852                 : nsSVGElement::NumberPairInfo nsSVGFELightingElement::sNumberPairInfo[1] =
    4853                 : {
    4854                 :   { &nsGkAtoms::kernelUnitLength, 0, 0 }
    4855                 : };
    4856                 : 
    4857                 : nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] =
    4858                 : {
    4859                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    4860                 :   { &nsGkAtoms::in, kNameSpaceID_None, true }
    4861                 : };
    4862                 : 
    4863                 : //----------------------------------------------------------------------
    4864                 : // nsISupports methods
    4865                 : 
    4866               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase)
    4867               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase)
    4868                 : 
    4869               0 : NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement) 
    4870               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase)
    4871                 : 
    4872                 : //----------------------------------------------------------------------
    4873                 : // Implementation
    4874                 : 
    4875                 : NS_IMETHODIMP_(bool)
    4876               0 : nsSVGFELightingElement::IsAttributeMapped(const nsIAtom* name) const
    4877                 : {
    4878                 :   static const MappedAttributeEntry* const map[] = {
    4879                 :     sLightingEffectsMap
    4880                 :   };
    4881                 : 
    4882               0 :   return FindAttributeDependence(name, map) ||
    4883               0 :     nsSVGFELightingElementBase::IsAttributeMapped(name);
    4884                 : }
    4885                 : 
    4886                 : void
    4887               0 : nsSVGFELightingElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    4888                 : {
    4889               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    4890               0 : }
    4891                 : 
    4892                 : void
    4893               0 : nsSVGFELightingElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    4894                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
    4895                 : {
    4896                 :   // XXX lighting can depend on more than the target area, because
    4897                 :   // of the kernels it uses. We could compute something precise here
    4898                 :   // but just leave it and assume we use the entire source bounding box.
    4899               0 : }
    4900                 : 
    4901                 : nsIntRect
    4902               0 : nsSVGFELightingElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    4903                 :                                           const nsSVGFilterInstance& aInstance)
    4904                 : {
    4905                 :   // XXX be conservative for now
    4906               0 :   return GetMaxRect();
    4907                 : }
    4908                 : 
    4909                 : #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
    4910                 : #define NORMALIZE(vec) \
    4911                 :   PR_BEGIN_MACRO \
    4912                 :     float norm = sqrt(DOT(vec, vec)); \
    4913                 :     vec[0] /= norm; \
    4914                 :     vec[1] /= norm; \
    4915                 :     vec[2] /= norm; \
    4916                 :   PR_END_MACRO
    4917                 : 
    4918                 : static PRInt32
    4919               0 : Convolve3x3(const PRUint8 *index, PRInt32 stride,
    4920                 :             const PRInt8 kernel[3][3])
    4921                 : {
    4922               0 :   PRInt32 sum = 0;
    4923               0 :   for (PRInt32 y = 0; y < 3; y++) {
    4924               0 :     for (PRInt32 x = 0; x < 3; x++) {
    4925               0 :       PRInt8 k = kernel[y][x];
    4926               0 :       if (k)
    4927               0 :         sum += k * index[4 * (x - 1) + stride * (y - 1)];
    4928                 :     }
    4929                 :   }
    4930               0 :   return sum;
    4931                 : }
    4932                 : 
    4933                 : static void
    4934               0 : GenerateNormal(float *N, const PRUint8 *data, PRInt32 stride,
    4935                 :                PRInt32 surfaceWidth, PRInt32 surfaceHeight,
    4936                 :                PRInt32 x, PRInt32 y, float surfaceScale)
    4937                 : {
    4938                 :   // See this for source of constants:
    4939                 :   //   http://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement
    4940                 :   static const PRInt8 Kx[3][3][3][3] =
    4941                 :     { { { {  0,  0,  0}, { 0, -2,  2}, { 0, -1,  1} },
    4942                 :         { {  0,  0,  0}, {-2,  0,  2}, {-1,  0,  1} },
    4943                 :         { {  0,  0,  0}, {-2,  2,  0}, {-1,  1,  0} } },
    4944                 :       { { {  0, -1,  1}, { 0, -2,  2}, { 0, -1,  1} },
    4945                 :         { { -1,  0,  1}, {-2,  0,  2}, {-1,  0,  1} },
    4946                 :         { { -1,  1,  0}, {-2,  2,  0}, {-1,  1,  0} } },
    4947                 :       { { {  0, -1,  1}, { 0, -2,  2}, { 0,  0,  0} },
    4948                 :         { { -1,  0,  1}, {-2,  0,  2}, { 0,  0,  0} },
    4949                 :         { { -1,  1,  0}, {-2,  2,  0}, { 0,  0,  0} } } };
    4950                 :   static const PRInt8 Ky[3][3][3][3] =
    4951                 :     { { { {  0,  0,  0}, { 0, -2, -1}, { 0,  2,  1} },
    4952                 :         { {  0,  0,  0}, {-1, -2, -1}, { 1,  2,  1} },
    4953                 :         { {  0,  0,  0}, {-1, -2,  1}, { 1,  2,  0} } },
    4954                 :       { { {  0, -2, -1}, { 0,  0,  0}, { 0,  2,  1} },
    4955                 :         { { -1, -2, -1}, { 0,  0,  0}, { 1,  2,  1} },
    4956                 :         { { -1, -2,  0}, { 0,  0,  0}, { 1,  2,  0} } },
    4957                 :       { { {  0, -2, -1}, { 0,  2,  1}, { 0,  0,  0} },
    4958                 :         { { -1, -2, -1}, { 1,  2,  1}, { 0,  0,  0} },
    4959                 :         { { -1, -2,  0}, { 1,  2,  0}, { 0,  0,  0} } } };
    4960                 :   static const float FACTORx[3][3] =
    4961                 :     { { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 },
    4962                 :       { 1.0 / 2.0, 1.0 / 4.0, 1.0 / 2.0 },
    4963                 :       { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 } };
    4964                 :   static const float FACTORy[3][3] =
    4965                 :     { { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 },
    4966                 :       { 1.0 / 3.0, 1.0 / 4.0, 1.0 / 3.0 },
    4967                 :       { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 } };
    4968                 : 
    4969                 :   // degenerate cases
    4970               0 :   if (surfaceWidth == 1 || surfaceHeight == 1) {
    4971                 :     // just return a unit vector pointing towards the viewer
    4972               0 :     N[0] = 0;
    4973               0 :     N[1] = 0;
    4974               0 :     N[2] = 255;
    4975               0 :     return;
    4976                 :   }
    4977                 : 
    4978                 :   PRInt8 xflag, yflag;
    4979               0 :   if (x == 0) {
    4980               0 :     xflag = 0;
    4981               0 :   } else if (x == surfaceWidth - 1) {
    4982               0 :     xflag = 2;
    4983                 :   } else {
    4984               0 :     xflag = 1;
    4985                 :   }
    4986               0 :   if (y == 0) {
    4987               0 :     yflag = 0;
    4988               0 :   } else if (y == surfaceHeight - 1) {
    4989               0 :     yflag = 2;
    4990                 :   } else {
    4991               0 :     yflag = 1;
    4992                 :   }
    4993                 : 
    4994               0 :   const PRUint8 *index = data + y * stride + 4 * x + GFX_ARGB32_OFFSET_A;
    4995                 : 
    4996               0 :   N[0] = -surfaceScale * FACTORx[yflag][xflag] *
    4997               0 :     Convolve3x3(index, stride, Kx[yflag][xflag]);
    4998               0 :   N[1] = -surfaceScale * FACTORy[yflag][xflag] *
    4999               0 :     Convolve3x3(index, stride, Ky[yflag][xflag]);
    5000               0 :   N[2] = 255;
    5001               0 :   NORMALIZE(N);
    5002                 : }
    5003                 : 
    5004                 : nsresult
    5005               0 : nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance,
    5006                 :                                const nsTArray<const Image*>& aSources,
    5007                 :                                const Image* aTarget,
    5008                 :                                const nsIntRect& rect)
    5009                 : {
    5010               0 :   ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect,
    5011               0 :                                       &mNumberPairAttributes[KERNEL_UNIT_LENGTH]);
    5012               0 :   if (!info.mTarget)
    5013               0 :     return NS_ERROR_FAILURE;
    5014                 : 
    5015               0 :   nsCOMPtr<nsIDOMSVGFEDistantLightElement> distantLight;
    5016               0 :   nsCOMPtr<nsIDOMSVGFEPointLightElement> pointLight;
    5017               0 :   nsCOMPtr<nsIDOMSVGFESpotLightElement> spotLight;
    5018                 : 
    5019               0 :   nsIFrame* frame = GetPrimaryFrame();
    5020               0 :   if (!frame) return NS_ERROR_FAILURE;
    5021               0 :   nsStyleContext* style = frame->GetStyleContext();
    5022                 : 
    5023               0 :   nscolor lightColor = style->GetStyleSVGReset()->mLightingColor;
    5024                 : 
    5025                 :   // find specified light  
    5026               0 :   for (nsCOMPtr<nsIContent> child = nsINode::GetFirstChild();
    5027               0 :        child;
    5028               0 :        child = child->GetNextSibling()) {
    5029               0 :     distantLight = do_QueryInterface(child);
    5030               0 :     pointLight = do_QueryInterface(child);
    5031               0 :     spotLight = do_QueryInterface(child);
    5032               0 :     if (distantLight || pointLight || spotLight)
    5033               0 :       break;
    5034                 :   }
    5035                 : 
    5036               0 :   if (!distantLight && !pointLight && !spotLight)
    5037               0 :     return NS_ERROR_FAILURE;
    5038                 : 
    5039               0 :   const float radPerDeg = M_PI/180.0;
    5040                 : 
    5041                 :   float L[3];
    5042               0 :   if (distantLight) {
    5043                 :     float azimuth, elevation;
    5044                 :     static_cast<nsSVGFEDistantLightElement*>
    5045               0 :       (distantLight.get())->GetAnimatedNumberValues(&azimuth,
    5046                 :                                                     &elevation,
    5047               0 :                                                     nsnull);
    5048               0 :     L[0] = cos(azimuth * radPerDeg) * cos(elevation * radPerDeg);
    5049               0 :     L[1] = sin(azimuth * radPerDeg) * cos(elevation * radPerDeg);
    5050               0 :     L[2] = sin(elevation * radPerDeg);
    5051                 :   }
    5052                 :   float lightPos[3], pointsAt[3], specularExponent;
    5053               0 :   float cosConeAngle = 0;
    5054               0 :   if (pointLight) {
    5055                 :     static_cast<nsSVGFEPointLightElement*>
    5056               0 :       (pointLight.get())->GetAnimatedNumberValues(lightPos,
    5057                 :                                                   lightPos + 1,
    5058                 :                                                   lightPos + 2,
    5059               0 :                                                   nsnull);
    5060               0 :     instance->ConvertLocation(lightPos);
    5061                 :   }
    5062               0 :   if (spotLight) {
    5063                 :     float limitingConeAngle;
    5064                 :     nsSVGFESpotLightElement* spot = 
    5065               0 :       static_cast<nsSVGFESpotLightElement*>(spotLight.get());
    5066                 :     spot->GetAnimatedNumberValues(lightPos,
    5067                 :                                   lightPos + 1,
    5068                 :                                   lightPos + 2,
    5069                 :                                   pointsAt,
    5070                 :                                   pointsAt + 1,
    5071                 :                                   pointsAt + 2,
    5072                 :                                   &specularExponent,
    5073                 :                                   &limitingConeAngle,
    5074               0 :                                   nsnull);
    5075               0 :     instance->ConvertLocation(lightPos);
    5076               0 :     instance->ConvertLocation(pointsAt);
    5077                 : 
    5078               0 :     if (spot->mNumberAttributes[nsSVGFESpotLightElement::LIMITING_CONE_ANGLE].
    5079               0 :                                   IsExplicitlySet()) {
    5080               0 :       cosConeAngle = NS_MAX<double>(cos(limitingConeAngle * radPerDeg), 0.0);
    5081                 :     }
    5082                 :   }
    5083                 : 
    5084               0 :   float surfaceScale = mNumberAttributes[SURFACE_SCALE].GetAnimValue();
    5085                 : 
    5086               0 :   const nsIntRect& dataRect = info.mDataRect;
    5087               0 :   PRInt32 stride = info.mSource->Stride();
    5088               0 :   PRUint8 *sourceData = info.mSource->Data();
    5089               0 :   PRUint8 *targetData = info.mTarget->Data();
    5090               0 :   PRInt32 surfaceWidth = info.mSource->Width();
    5091               0 :   PRInt32 surfaceHeight = info.mSource->Height();
    5092                 :   
    5093               0 :   for (PRInt32 y = dataRect.y; y < dataRect.YMost(); y++) {
    5094               0 :     for (PRInt32 x = dataRect.x; x < dataRect.XMost(); x++) {
    5095               0 :       PRInt32 index = y * stride + x * 4;
    5096                 : 
    5097                 :       float N[3];
    5098                 :       GenerateNormal(N, sourceData, stride, surfaceWidth, surfaceHeight,
    5099               0 :                      x, y, surfaceScale);
    5100                 : 
    5101               0 :       if (pointLight || spotLight) {
    5102                 :         gfxPoint pt = instance->FilterSpaceToUserSpace(
    5103               0 :                 gfxPoint(x + instance->GetSurfaceRect().x,
    5104               0 :                          y + instance->GetSurfaceRect().y));
    5105               0 :         float Z = surfaceScale * sourceData[index + GFX_ARGB32_OFFSET_A] / 255;
    5106                 : 
    5107               0 :         L[0] = lightPos[0] - pt.x;
    5108               0 :         L[1] = lightPos[1] - pt.y;
    5109               0 :         L[2] = lightPos[2] - Z;
    5110               0 :         NORMALIZE(L);
    5111                 :       }
    5112                 : 
    5113                 :       nscolor color;
    5114                 : 
    5115               0 :       if (spotLight) {
    5116                 :         float S[3];
    5117               0 :         S[0] = pointsAt[0] - lightPos[0];
    5118               0 :         S[1] = pointsAt[1] - lightPos[1];
    5119               0 :         S[2] = pointsAt[2] - lightPos[2];
    5120               0 :         NORMALIZE(S);
    5121               0 :         float dot = -DOT(L, S);
    5122               0 :         if (dot < cosConeAngle) {
    5123               0 :           color = NS_RGB(0, 0, 0);
    5124                 :         } else {
    5125               0 :           float tmp = pow(dot, specularExponent);
    5126                 :           color = NS_RGB(PRUint8(NS_GET_R(lightColor) * tmp),
    5127                 :                          PRUint8(NS_GET_G(lightColor) * tmp),
    5128               0 :                          PRUint8(NS_GET_B(lightColor) * tmp));
    5129                 :         }
    5130                 :       } else {
    5131               0 :         color = lightColor;
    5132                 :       }
    5133                 : 
    5134               0 :       LightPixel(N, L, color, targetData + index);
    5135                 :     }
    5136                 :   }
    5137                 : 
    5138               0 :   FinishScalingFilter(&info);
    5139                 : 
    5140               0 :   return NS_OK;
    5141                 : }
    5142                 : 
    5143                 : bool
    5144               0 : nsSVGFELightingElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    5145                 :                                                   nsIAtom* aAttribute) const
    5146                 : {
    5147               0 :   return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    5148                 :          (aNameSpaceID == kNameSpaceID_None &&
    5149                 :           (aAttribute == nsGkAtoms::in ||
    5150                 :            aAttribute == nsGkAtoms::surfaceScale ||
    5151               0 :            aAttribute == nsGkAtoms::kernelUnitLength));
    5152                 : }
    5153                 : 
    5154                 : //----------------------------------------------------------------------
    5155                 : // nsSVGElement methods
    5156                 : 
    5157                 : nsSVGElement::NumberAttributesInfo
    5158               0 : nsSVGFELightingElement::GetNumberInfo()
    5159                 : {
    5160                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    5161               0 :                               ArrayLength(sNumberInfo));
    5162                 : }
    5163                 : 
    5164                 : nsSVGElement::NumberPairAttributesInfo
    5165               0 : nsSVGFELightingElement::GetNumberPairInfo()
    5166                 : {
    5167                 :   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
    5168               0 :                                   ArrayLength(sNumberPairInfo));
    5169                 : }
    5170                 : 
    5171                 : nsSVGElement::StringAttributesInfo
    5172               0 : nsSVGFELightingElement::GetStringInfo()
    5173                 : {
    5174                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    5175               0 :                               ArrayLength(sStringInfo));
    5176                 : }
    5177                 : 
    5178                 : //---------------------DiffuseLighting------------------------
    5179                 : 
    5180                 : typedef nsSVGFELightingElement nsSVGFEDiffuseLightingElementBase;
    5181                 : 
    5182                 : class nsSVGFEDiffuseLightingElement : public nsSVGFEDiffuseLightingElementBase,
    5183                 :                                       public nsIDOMSVGFEDiffuseLightingElement
    5184               0 : {
    5185                 :   friend nsresult NS_NewSVGFEDiffuseLightingElement(nsIContent **aResult,
    5186                 :                                                     already_AddRefed<nsINodeInfo> aNodeInfo);
    5187                 : protected:
    5188               0 :   nsSVGFEDiffuseLightingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    5189               0 :     : nsSVGFEDiffuseLightingElementBase(aNodeInfo) {}
    5190                 : 
    5191                 : public:
    5192                 :   // interfaces:
    5193                 :   NS_DECL_ISUPPORTS_INHERITED
    5194                 : 
    5195                 :   // DiffuseLighting
    5196                 :   NS_DECL_NSIDOMSVGFEDIFFUSELIGHTINGELEMENT
    5197                 : 
    5198               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEDiffuseLightingElementBase::)
    5199               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEDiffuseLightingElementBase::)
    5200               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEDiffuseLightingElementBase::)
    5201               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEDiffuseLightingElementBase::)
    5202                 : 
    5203                 :   virtual bool AttributeAffectsRendering(
    5204                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    5205                 : 
    5206                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    5207                 : 
    5208                 :   virtual nsXPCClassInfo* GetClassInfo();
    5209                 : protected:
    5210                 :   virtual void LightPixel(const float *N, const float *L,
    5211                 :                           nscolor color, PRUint8 *targetData);
    5212                 : 
    5213                 : };
    5214                 : 
    5215               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEDiffuseLighting)
    5216                 : 
    5217                 : //----------------------------------------------------------------------
    5218                 : // nsISupports methods
    5219                 : 
    5220               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEDiffuseLightingElement,nsSVGFEDiffuseLightingElementBase)
    5221               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEDiffuseLightingElement,nsSVGFEDiffuseLightingElementBase)
    5222                 : 
    5223               0 : DOMCI_NODE_DATA(SVGFEDiffuseLightingElement, nsSVGFEDiffuseLightingElement)
    5224                 : 
    5225               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEDiffuseLightingElement)
    5226               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEDiffuseLightingElement, nsIDOMNode,
    5227                 :                            nsIDOMElement, nsIDOMSVGElement,
    5228                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    5229                 :                            nsIDOMSVGFEDiffuseLightingElement)
    5230               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEDiffuseLightingElement)
    5231               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEDiffuseLightingElementBase)
    5232                 : 
    5233                 : //----------------------------------------------------------------------
    5234                 : // nsIDOMNode methods
    5235                 : 
    5236               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEDiffuseLightingElement)
    5237                 : 
    5238                 : //----------------------------------------------------------------------
    5239                 : // nsSVGFEDiffuseLightingElement methods
    5240                 : 
    5241                 : NS_IMETHODIMP
    5242               0 : nsSVGFEDiffuseLightingElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    5243                 : {
    5244               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    5245                 : }
    5246                 : 
    5247                 : NS_IMETHODIMP
    5248               0 : nsSVGFEDiffuseLightingElement::GetSurfaceScale(nsIDOMSVGAnimatedNumber **aScale)
    5249                 : {
    5250                 :   return mNumberAttributes[SURFACE_SCALE].ToDOMAnimatedNumber(aScale,
    5251               0 :                                                               this);
    5252                 : }
    5253                 : 
    5254                 : NS_IMETHODIMP
    5255               0 : nsSVGFEDiffuseLightingElement::GetDiffuseConstant(nsIDOMSVGAnimatedNumber **aConstant)
    5256                 : {
    5257                 :   return mNumberAttributes[DIFFUSE_CONSTANT].ToDOMAnimatedNumber(aConstant,
    5258               0 :                                                               this);
    5259                 : }
    5260                 : 
    5261                 : NS_IMETHODIMP
    5262               0 : nsSVGFEDiffuseLightingElement::GetKernelUnitLengthX(nsIDOMSVGAnimatedNumber **aKernelX)
    5263                 : {
    5264                 :   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelX,
    5265                 :                                                                        nsSVGNumberPair::eFirst,
    5266               0 :                                                                        this);
    5267                 : }
    5268                 : 
    5269                 : NS_IMETHODIMP
    5270               0 : nsSVGFEDiffuseLightingElement::GetKernelUnitLengthY(nsIDOMSVGAnimatedNumber **aKernelY)
    5271                 : {
    5272                 :   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelY,
    5273                 :                                                                        nsSVGNumberPair::eSecond,
    5274               0 :                                                                        this);
    5275                 : }
    5276                 : 
    5277                 : bool
    5278               0 : nsSVGFEDiffuseLightingElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    5279                 :                                                          nsIAtom* aAttribute) const
    5280                 : {
    5281               0 :   return nsSVGFEDiffuseLightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    5282                 :          (aNameSpaceID == kNameSpaceID_None &&
    5283               0 :           aAttribute == nsGkAtoms::diffuseConstant);
    5284                 : }
    5285                 : 
    5286                 : //----------------------------------------------------------------------
    5287                 : // nsSVGElement methods
    5288                 : 
    5289                 : void
    5290               0 : nsSVGFEDiffuseLightingElement::LightPixel(const float *N, const float *L,
    5291                 :                                           nscolor color, PRUint8 *targetData)
    5292                 : {
    5293                 :   float diffuseNL =
    5294               0 :     mNumberAttributes[DIFFUSE_CONSTANT].GetAnimValue() * DOT(N, L);
    5295                 : 
    5296               0 :   if (diffuseNL > 0) {
    5297                 :     targetData[GFX_ARGB32_OFFSET_B] =
    5298               0 :       NS_MIN(PRUint32(diffuseNL * NS_GET_B(color)), 255U);
    5299               0 :     targetData[GFX_ARGB32_OFFSET_G] =
    5300               0 :       NS_MIN(PRUint32(diffuseNL * NS_GET_G(color)), 255U);
    5301               0 :     targetData[GFX_ARGB32_OFFSET_R] =
    5302               0 :       NS_MIN(PRUint32(diffuseNL * NS_GET_R(color)), 255U);
    5303                 :   } else {
    5304               0 :     targetData[GFX_ARGB32_OFFSET_B] = 0;
    5305               0 :     targetData[GFX_ARGB32_OFFSET_G] = 0;
    5306               0 :     targetData[GFX_ARGB32_OFFSET_R] = 0;
    5307                 :   }
    5308                 : 
    5309               0 :   targetData[GFX_ARGB32_OFFSET_A] = 255;
    5310               0 : }
    5311                 : 
    5312                 : //---------------------SpecularLighting------------------------
    5313                 : 
    5314                 : typedef nsSVGFELightingElement nsSVGFESpecularLightingElementBase;
    5315                 : 
    5316                 : class nsSVGFESpecularLightingElement : public nsSVGFESpecularLightingElementBase,
    5317                 :                                        public nsIDOMSVGFESpecularLightingElement
    5318               0 : {
    5319                 :   friend nsresult NS_NewSVGFESpecularLightingElement(nsIContent **aResult,
    5320                 :                                                already_AddRefed<nsINodeInfo> aNodeInfo);
    5321                 : protected:
    5322               0 :   nsSVGFESpecularLightingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    5323               0 :     : nsSVGFESpecularLightingElementBase(aNodeInfo) {}
    5324                 : 
    5325                 : public:
    5326                 :   // interfaces:
    5327                 :   NS_DECL_ISUPPORTS_INHERITED
    5328                 : 
    5329                 :   // DiffuseLighting
    5330                 :   NS_DECL_NSIDOMSVGFESPECULARLIGHTINGELEMENT
    5331                 : 
    5332               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFESpecularLightingElementBase::)
    5333               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFESpecularLightingElementBase::)
    5334               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFESpecularLightingElementBase::)
    5335               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFESpecularLightingElementBase::)
    5336                 : 
    5337                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    5338                 : 
    5339                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    5340                 :                           const nsTArray<const Image*>& aSources,
    5341                 :                           const Image* aTarget,
    5342                 :                           const nsIntRect& aDataRect);
    5343                 :   virtual bool AttributeAffectsRendering(
    5344                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    5345                 : 
    5346                 :   virtual nsXPCClassInfo* GetClassInfo();
    5347                 : protected:
    5348                 :   virtual void LightPixel(const float *N, const float *L,
    5349                 :                           nscolor color, PRUint8 *targetData);
    5350                 : 
    5351                 : };
    5352                 : 
    5353               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FESpecularLighting)
    5354                 : 
    5355                 : //----------------------------------------------------------------------
    5356                 : // nsISupports methods
    5357                 : 
    5358               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFESpecularLightingElement,nsSVGFESpecularLightingElementBase)
    5359               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFESpecularLightingElement,nsSVGFESpecularLightingElementBase)
    5360                 : 
    5361               0 : DOMCI_NODE_DATA(SVGFESpecularLightingElement, nsSVGFESpecularLightingElement)
    5362                 : 
    5363               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFESpecularLightingElement)
    5364               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFESpecularLightingElement, nsIDOMNode,
    5365                 :                            nsIDOMElement, nsIDOMSVGElement,
    5366                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    5367                 :                            nsIDOMSVGFESpecularLightingElement)
    5368               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFESpecularLightingElement)
    5369               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFESpecularLightingElementBase)
    5370                 : 
    5371                 : //----------------------------------------------------------------------
    5372                 : // nsIDOMNode methods
    5373                 : 
    5374               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFESpecularLightingElement)
    5375                 : 
    5376                 : //----------------------------------------------------------------------
    5377                 : // nsSVGFESpecularLightingElement methods
    5378                 : 
    5379                 : NS_IMETHODIMP
    5380               0 : nsSVGFESpecularLightingElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    5381                 : {
    5382               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    5383                 : }
    5384                 : 
    5385                 : NS_IMETHODIMP
    5386               0 : nsSVGFESpecularLightingElement::GetSurfaceScale(nsIDOMSVGAnimatedNumber **aScale)
    5387                 : {
    5388                 :   return mNumberAttributes[SURFACE_SCALE].ToDOMAnimatedNumber(aScale,
    5389               0 :                                                               this);
    5390                 : }
    5391                 : 
    5392                 : NS_IMETHODIMP
    5393               0 : nsSVGFESpecularLightingElement::GetSpecularConstant(nsIDOMSVGAnimatedNumber **aConstant)
    5394                 : {
    5395                 :   return mNumberAttributes[SPECULAR_CONSTANT].ToDOMAnimatedNumber(aConstant,
    5396               0 :                                                                   this);
    5397                 : }
    5398                 : 
    5399                 : NS_IMETHODIMP
    5400               0 : nsSVGFESpecularLightingElement::GetSpecularExponent(nsIDOMSVGAnimatedNumber **aExponent)
    5401                 : {
    5402                 :   return mNumberAttributes[SPECULAR_EXPONENT].ToDOMAnimatedNumber(aExponent,
    5403               0 :                                                                   this);
    5404                 : }
    5405                 : 
    5406                 : NS_IMETHODIMP
    5407               0 : nsSVGFESpecularLightingElement::GetKernelUnitLengthX(nsIDOMSVGAnimatedNumber **aKernelX)
    5408                 : {
    5409                 :   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelX,
    5410                 :                                                                        nsSVGNumberPair::eFirst,
    5411               0 :                                                                        this);
    5412                 : }
    5413                 : 
    5414                 : NS_IMETHODIMP
    5415               0 : nsSVGFESpecularLightingElement::GetKernelUnitLengthY(nsIDOMSVGAnimatedNumber **aKernelY)
    5416                 : {
    5417                 :   return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelY,
    5418                 :                                                                        nsSVGNumberPair::eSecond,
    5419               0 :                                                                        this);
    5420                 : }
    5421                 : 
    5422                 : //----------------------------------------------------------------------
    5423                 : // nsSVGElement methods
    5424                 : 
    5425                 : nsresult
    5426               0 : nsSVGFESpecularLightingElement::Filter(nsSVGFilterInstance *instance,
    5427                 :                                        const nsTArray<const Image*>& aSources,
    5428                 :                                        const Image* aTarget,
    5429                 :                                        const nsIntRect& rect)
    5430                 : {
    5431               0 :   float specularExponent = mNumberAttributes[SPECULAR_EXPONENT].GetAnimValue();
    5432                 : 
    5433                 :   // specification defined range (15.22)
    5434               0 :   if (specularExponent < 1 || specularExponent > 128)
    5435               0 :     return NS_ERROR_FAILURE;
    5436                 : 
    5437               0 :   return nsSVGFESpecularLightingElementBase::Filter(instance, aSources, aTarget, rect);
    5438                 : }
    5439                 : 
    5440                 : bool
    5441               0 : nsSVGFESpecularLightingElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    5442                 :                                                           nsIAtom* aAttribute) const
    5443                 : {
    5444               0 :   return nsSVGFESpecularLightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    5445                 :          (aNameSpaceID == kNameSpaceID_None &&
    5446                 :           (aAttribute == nsGkAtoms::specularConstant ||
    5447               0 :            aAttribute == nsGkAtoms::specularExponent));
    5448                 : }
    5449                 : 
    5450                 : void
    5451               0 : nsSVGFESpecularLightingElement::LightPixel(const float *N, const float *L,
    5452                 :                                            nscolor color, PRUint8 *targetData)
    5453                 : {
    5454                 :   float H[3];
    5455               0 :   H[0] = L[0];
    5456               0 :   H[1] = L[1];
    5457               0 :   H[2] = L[2] + 1;
    5458               0 :   NORMALIZE(H);
    5459                 : 
    5460               0 :   float kS = mNumberAttributes[SPECULAR_CONSTANT].GetAnimValue();
    5461               0 :   float dotNH = DOT(N, H);
    5462                 : 
    5463               0 :   if (dotNH > 0 && kS > 0) {
    5464                 :     float specularNH =
    5465               0 :       kS * pow(dotNH, mNumberAttributes[SPECULAR_EXPONENT].GetAnimValue());
    5466                 : 
    5467                 :     targetData[GFX_ARGB32_OFFSET_B] =
    5468               0 :       NS_MIN(PRUint32(specularNH * NS_GET_B(color)), 255U);
    5469               0 :     targetData[GFX_ARGB32_OFFSET_G] =
    5470               0 :       NS_MIN(PRUint32(specularNH * NS_GET_G(color)), 255U);
    5471               0 :     targetData[GFX_ARGB32_OFFSET_R] =
    5472               0 :       NS_MIN(PRUint32(specularNH * NS_GET_R(color)), 255U);
    5473                 : 
    5474               0 :     targetData[GFX_ARGB32_OFFSET_A] =
    5475                 :       NS_MAX(targetData[GFX_ARGB32_OFFSET_B],
    5476                 :              NS_MAX(targetData[GFX_ARGB32_OFFSET_G],
    5477               0 :                     targetData[GFX_ARGB32_OFFSET_R]));
    5478                 :   } else {
    5479               0 :     targetData[GFX_ARGB32_OFFSET_B] = 0;
    5480               0 :     targetData[GFX_ARGB32_OFFSET_G] = 0;
    5481               0 :     targetData[GFX_ARGB32_OFFSET_R] = 0;
    5482               0 :     targetData[GFX_ARGB32_OFFSET_A] = 255;
    5483                 :   }
    5484               0 : }
    5485                 : 
    5486                 : //---------------------Image------------------------
    5487                 : 
    5488                 : nsSVGElement::StringInfo nsSVGFEImageElement::sStringInfo[2] =
    5489                 : {
    5490                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    5491                 :   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
    5492                 : };
    5493                 : 
    5494               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEImage)
    5495                 : 
    5496                 : //----------------------------------------------------------------------
    5497                 : // nsISupports methods
    5498                 : 
    5499               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEImageElement,nsSVGFEImageElementBase)
    5500               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEImageElement,nsSVGFEImageElementBase)
    5501                 : 
    5502               0 : DOMCI_NODE_DATA(SVGFEImageElement, nsSVGFEImageElement)
    5503                 : 
    5504               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEImageElement)
    5505               0 :   NS_NODE_INTERFACE_TABLE8(nsSVGFEImageElement, nsIDOMNode, nsIDOMElement,
    5506                 :                            nsIDOMSVGElement,
    5507                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    5508                 :                            nsIDOMSVGFEImageElement, nsIDOMSVGURIReference,
    5509                 :                            imgIDecoderObserver, nsIImageLoadingContent)
    5510               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEImageElement)
    5511               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEImageElementBase)
    5512                 : 
    5513                 : //----------------------------------------------------------------------
    5514                 : // Implementation
    5515                 : 
    5516               0 : nsSVGFEImageElement::nsSVGFEImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    5517               0 :   : nsSVGFEImageElementBase(aNodeInfo)
    5518                 : {
    5519                 :   // We start out broken
    5520               0 :   AddStatesSilently(NS_EVENT_STATE_BROKEN);
    5521               0 : }
    5522                 : 
    5523               0 : nsSVGFEImageElement::~nsSVGFEImageElement()
    5524                 : {
    5525               0 :   DestroyImageLoadingContent();
    5526               0 : }
    5527                 : 
    5528                 : //----------------------------------------------------------------------
    5529                 : 
    5530                 : nsresult
    5531               0 : nsSVGFEImageElement::LoadSVGImage(bool aForce, bool aNotify)
    5532                 : {
    5533                 :   // resolve href attribute
    5534               0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    5535                 : 
    5536               0 :   nsAutoString href;
    5537               0 :   mStringAttributes[HREF].GetAnimValue(href, this);
    5538               0 :   href.Trim(" \t\n\r");
    5539                 : 
    5540               0 :   if (baseURI && !href.IsEmpty())
    5541               0 :     NS_MakeAbsoluteURI(href, href, baseURI);
    5542                 : 
    5543                 :   // Make sure we don't get in a recursive death-spiral
    5544               0 :   nsIDocument* doc = OwnerDoc();
    5545               0 :   nsCOMPtr<nsIURI> hrefAsURI;
    5546               0 :   if (NS_SUCCEEDED(StringToURI(href, doc, getter_AddRefs(hrefAsURI)))) {
    5547                 :     bool isEqual;
    5548               0 :     if (NS_SUCCEEDED(hrefAsURI->Equals(baseURI, &isEqual)) && isEqual) {
    5549                 :       // Image URI matches our URI exactly! Bail out.
    5550               0 :       return NS_OK;
    5551                 :     }
    5552                 :   }
    5553                 : 
    5554               0 :   return LoadImage(href, aForce, aNotify);
    5555                 : }
    5556                 : 
    5557                 : //----------------------------------------------------------------------
    5558                 : // nsIContent methods:
    5559                 : 
    5560                 : NS_IMETHODIMP_(bool)
    5561               0 : nsSVGFEImageElement::IsAttributeMapped(const nsIAtom* name) const
    5562                 : {
    5563                 :   static const MappedAttributeEntry* const map[] = {
    5564                 :     sGraphicsMap
    5565                 :   };
    5566                 :   
    5567               0 :   return FindAttributeDependence(name, map) ||
    5568               0 :     nsSVGFEImageElementBase::IsAttributeMapped(name);
    5569                 : }
    5570                 : 
    5571                 : nsresult
    5572               0 : nsSVGFEImageElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
    5573                 :                                   const nsAttrValue* aValue, bool aNotify)
    5574                 : {
    5575               0 :   if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) {
    5576                 : 
    5577                 :     // If there isn't a frame we still need to load the image in case
    5578                 :     // the frame is created later e.g. by attaching to a document.
    5579                 :     // If there is a frame then it should deal with loading as the image
    5580                 :     // url may be animated.
    5581               0 :     if (!GetPrimaryFrame()) {
    5582                 : 
    5583                 :       // Prevent setting image.src by exiting early
    5584               0 :       if (nsContentUtils::IsImageSrcSetDisabled()) {
    5585               0 :         return NS_OK;
    5586                 :       }
    5587               0 :       if (aValue) {
    5588               0 :         LoadSVGImage(true, aNotify);
    5589                 :       } else {
    5590               0 :         CancelImageRequests(aNotify);
    5591                 :       }
    5592                 :     }
    5593                 :   }
    5594                 : 
    5595                 :   return nsSVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName,
    5596               0 :                                                aValue, aNotify);
    5597                 : }
    5598                 : 
    5599                 : void
    5600               0 : nsSVGFEImageElement::MaybeLoadSVGImage()
    5601                 : {
    5602               0 :   if (mStringAttributes[HREF].IsExplicitlySet() &&
    5603               0 :       (NS_FAILED(LoadSVGImage(false, true)) ||
    5604               0 :        !LoadingEnabled())) {
    5605               0 :     CancelImageRequests(true);
    5606                 :   }
    5607               0 : }
    5608                 : 
    5609                 : nsresult
    5610               0 : nsSVGFEImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    5611                 :                                 nsIContent* aBindingParent,
    5612                 :                                 bool aCompileEventHandlers)
    5613                 : {
    5614                 :   nsresult rv = nsSVGFEImageElementBase::BindToTree(aDocument, aParent,
    5615                 :                                                     aBindingParent,
    5616               0 :                                                     aCompileEventHandlers);
    5617               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5618                 : 
    5619               0 :   if (mStringAttributes[HREF].IsExplicitlySet()) {
    5620                 :     // FIXME: Bug 660963 it would be nice if we could just have
    5621                 :     // ClearBrokenState update our state and do it fast...
    5622               0 :     ClearBrokenState();
    5623               0 :     RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
    5624                 :     nsContentUtils::AddScriptRunner(
    5625               0 :       NS_NewRunnableMethod(this, &nsSVGFEImageElement::MaybeLoadSVGImage));
    5626                 :   }
    5627                 : 
    5628               0 :   return rv;
    5629                 : }
    5630                 : 
    5631                 : nsEventStates
    5632               0 : nsSVGFEImageElement::IntrinsicState() const
    5633                 : {
    5634                 :   return nsSVGFEImageElementBase::IntrinsicState() |
    5635               0 :     nsImageLoadingContent::ImageState();
    5636                 : }
    5637                 : 
    5638                 : //----------------------------------------------------------------------
    5639                 : // nsIDOMNode methods
    5640                 : 
    5641               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEImageElement)
    5642                 : 
    5643                 : //----------------------------------------------------------------------
    5644                 : // nsIDOMSVGURIReference methods:
    5645                 : 
    5646                 : /* readonly attribute nsIDOMSVGAnimatedString href; */
    5647                 : NS_IMETHODIMP
    5648               0 : nsSVGFEImageElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
    5649                 : {
    5650               0 :   return mStringAttributes[HREF].ToDOMAnimatedString(aHref, this);
    5651                 : }
    5652                 : 
    5653                 : //----------------------------------------------------------------------
    5654                 : // nsIDOMSVGFEImageElement methods
    5655                 : 
    5656                 : nsresult
    5657               0 : nsSVGFEImageElement::Filter(nsSVGFilterInstance *instance,
    5658                 :                             const nsTArray<const Image*>& aSources,
    5659                 :                             const Image* aTarget,
    5660                 :                             const nsIntRect& rect)
    5661                 : {
    5662               0 :   nsIFrame* frame = GetPrimaryFrame();
    5663               0 :   if (!frame) return NS_ERROR_FAILURE;
    5664                 : 
    5665               0 :   nsCOMPtr<imgIRequest> currentRequest;
    5666                 :   GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    5667               0 :              getter_AddRefs(currentRequest));
    5668                 : 
    5669               0 :   nsCOMPtr<imgIContainer> imageContainer;
    5670               0 :   if (currentRequest)
    5671               0 :     currentRequest->GetImage(getter_AddRefs(imageContainer));
    5672                 : 
    5673               0 :   nsRefPtr<gfxASurface> currentFrame;
    5674               0 :   if (imageContainer)
    5675               0 :     imageContainer->GetFrame(imgIContainer::FRAME_CURRENT,
    5676                 :                              imgIContainer::FLAG_SYNC_DECODE,
    5677               0 :                              getter_AddRefs(currentFrame));
    5678                 : 
    5679                 :   // We need to wrap the surface in a pattern to have somewhere to set the
    5680                 :   // graphics filter.
    5681               0 :   nsRefPtr<gfxPattern> thebesPattern;
    5682               0 :   if (currentFrame)
    5683               0 :     thebesPattern = new gfxPattern(currentFrame);
    5684                 : 
    5685               0 :   if (thebesPattern) {
    5686               0 :     thebesPattern->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(frame));
    5687                 : 
    5688                 :     PRInt32 nativeWidth, nativeHeight;
    5689               0 :     imageContainer->GetWidth(&nativeWidth);
    5690               0 :     imageContainer->GetHeight(&nativeHeight);
    5691                 : 
    5692               0 :     const gfxRect& filterSubregion = aTarget->mFilterPrimitiveSubregion;
    5693                 : 
    5694                 :     gfxMatrix viewBoxTM =
    5695                 :       nsSVGUtils::GetViewBoxTransform(this,
    5696               0 :                                       filterSubregion.Width(), filterSubregion.Height(),
    5697                 :                                       0,0, nativeWidth, nativeHeight,
    5698               0 :                                       mPreserveAspectRatio);
    5699                 : 
    5700               0 :     gfxMatrix xyTM = gfxMatrix().Translate(gfxPoint(filterSubregion.X(), filterSubregion.Y()));
    5701                 : 
    5702               0 :     gfxMatrix TM = viewBoxTM * xyTM;
    5703                 :     
    5704               0 :     nsRefPtr<gfxContext> ctx = new gfxContext(aTarget->mImage);
    5705               0 :     nsSVGUtils::CompositePatternMatrix(ctx, thebesPattern, TM, nativeWidth, nativeHeight, 1.0);
    5706                 :   }
    5707                 : 
    5708               0 :   return NS_OK;
    5709                 : }
    5710                 : 
    5711                 : bool
    5712               0 : nsSVGFEImageElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    5713                 :                                                nsIAtom* aAttribute) const
    5714                 : {
    5715                 :   // nsGkAtoms::href is deliberately omitted as the frame has special
    5716                 :   // handling to load the image
    5717               0 :   return nsSVGFEImageElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    5718                 :          (aNameSpaceID == kNameSpaceID_None &&
    5719               0 :           aAttribute == nsGkAtoms::preserveAspectRatio);
    5720                 : }
    5721                 : 
    5722                 : nsIntRect
    5723               0 : nsSVGFEImageElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    5724                 :         const nsSVGFilterInstance& aInstance)
    5725                 : {
    5726                 :   // XXX can do better here ... we could check what we know of the source
    5727                 :   // image bounds and compute an accurate bounding box for the filter
    5728                 :   // primitive result.
    5729               0 :   return GetMaxRect();
    5730                 : }
    5731                 : 
    5732                 : //----------------------------------------------------------------------
    5733                 : // nsSVGElement methods
    5734                 : 
    5735                 : SVGAnimatedPreserveAspectRatio *
    5736               0 : nsSVGFEImageElement::GetPreserveAspectRatio()
    5737                 : {
    5738               0 :   return &mPreserveAspectRatio;
    5739                 : }
    5740                 : 
    5741                 : nsSVGElement::StringAttributesInfo
    5742               0 : nsSVGFEImageElement::GetStringInfo()
    5743                 : {
    5744                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    5745               0 :                               ArrayLength(sStringInfo));
    5746                 : }
    5747                 : 
    5748                 : //----------------------------------------------------------------------
    5749                 : // imgIDecoderObserver methods
    5750                 : 
    5751                 : NS_IMETHODIMP
    5752               0 : nsSVGFEImageElement::OnStopDecode(imgIRequest *aRequest,
    5753                 :                                   nsresult status,
    5754                 :                                   const PRUnichar *statusArg)
    5755                 : {
    5756                 :   nsresult rv =
    5757               0 :     nsImageLoadingContent::OnStopDecode(aRequest, status, statusArg);
    5758               0 :   Invalidate();
    5759               0 :   return rv;
    5760                 : }
    5761                 : 
    5762                 : NS_IMETHODIMP
    5763               0 : nsSVGFEImageElement::FrameChanged(imgIRequest* aRequest,
    5764                 :                                   imgIContainer *aContainer,
    5765                 :                                   const nsIntRect *aDirtyRect)
    5766                 : {
    5767                 :   nsresult rv =
    5768               0 :     nsImageLoadingContent::FrameChanged(aRequest, aContainer, aDirtyRect);
    5769               0 :   Invalidate();
    5770               0 :   return rv;
    5771                 : }
    5772                 : 
    5773                 : NS_IMETHODIMP
    5774               0 : nsSVGFEImageElement::OnStartContainer(imgIRequest *aRequest,
    5775                 :                                       imgIContainer *aContainer)
    5776                 : {
    5777                 :   nsresult rv =
    5778               0 :     nsImageLoadingContent::OnStartContainer(aRequest, aContainer);
    5779                 : 
    5780                 :   // Request a decode
    5781               0 :   NS_ABORT_IF_FALSE(aContainer, "who sent the notification then?");
    5782               0 :   aContainer->RequestDecode();
    5783                 : 
    5784                 :   // We have a size - invalidate
    5785               0 :   Invalidate();
    5786               0 :   return rv;
    5787                 : }
    5788                 : 
    5789                 : //----------------------------------------------------------------------
    5790                 : // helper methods
    5791                 : 
    5792                 : void
    5793               0 : nsSVGFEImageElement::Invalidate()
    5794                 : {
    5795               0 :   nsCOMPtr<nsIDOMSVGFilterElement> filter = do_QueryInterface(GetParent());
    5796               0 :   if (filter) {
    5797               0 :     static_cast<nsSVGFilterElement*>(GetParent())->Invalidate();
    5798                 :   }
    5799               0 : }
    5800                 : 
    5801                 : //---------------------Displacement------------------------
    5802                 : 
    5803                 : typedef nsSVGFE nsSVGFEDisplacementMapElementBase;
    5804                 : 
    5805                 : class nsSVGFEDisplacementMapElement : public nsSVGFEDisplacementMapElementBase,
    5806                 :                                       public nsIDOMSVGFEDisplacementMapElement
    5807               0 : {
    5808                 : protected:
    5809                 :   friend nsresult NS_NewSVGFEDisplacementMapElement(nsIContent **aResult,
    5810                 :                                                     already_AddRefed<nsINodeInfo> aNodeInfo);
    5811               0 :   nsSVGFEDisplacementMapElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    5812               0 :     : nsSVGFEDisplacementMapElementBase(aNodeInfo) {}
    5813                 : 
    5814                 : public:
    5815                 :   // interfaces:
    5816                 :   NS_DECL_ISUPPORTS_INHERITED
    5817                 : 
    5818                 :   // FE Base
    5819               0 :   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEDisplacementMapElementBase::)
    5820                 : 
    5821                 :   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
    5822                 :                           const nsTArray<const Image*>& aSources,
    5823                 :                           const Image* aTarget,
    5824                 :                           const nsIntRect& aDataRect);
    5825                 :   virtual bool AttributeAffectsRendering(
    5826                 :           PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
    5827               0 :   virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
    5828                 :   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
    5829                 :   virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    5830                 :           const nsSVGFilterInstance& aInstance);
    5831                 :   virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    5832                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
    5833                 :   virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    5834                 :           const nsSVGFilterInstance& aInstance);
    5835                 : 
    5836                 :   // DisplacementMap
    5837                 :   NS_DECL_NSIDOMSVGFEDISPLACEMENTMAPELEMENT
    5838                 : 
    5839               0 :   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEDisplacementMapElementBase::)
    5840                 : 
    5841               0 :   NS_FORWARD_NSIDOMNODE(nsSVGFEDisplacementMapElementBase::)
    5842               0 :   NS_FORWARD_NSIDOMELEMENT(nsSVGFEDisplacementMapElementBase::)
    5843                 : 
    5844                 :   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
    5845                 : 
    5846                 :   virtual nsXPCClassInfo* GetClassInfo();
    5847                 : protected:
    5848               0 :   virtual bool OperatesOnSRGB(nsSVGFilterInstance* aInstance,
    5849                 :                                 PRInt32 aInput, Image* aImage) {
    5850               0 :     switch (aInput) {
    5851                 :     case 0:
    5852               0 :       return aImage->mColorModel.mColorSpace == ColorModel::SRGB;
    5853                 :     case 1:
    5854                 :       return nsSVGFEDisplacementMapElementBase::OperatesOnSRGB(aInstance,
    5855               0 :                                                                aInput, aImage);
    5856                 :     default:
    5857               0 :       NS_ERROR("Will not give correct output color model");
    5858               0 :       return false;
    5859                 :     }
    5860                 :   }
    5861               0 :   virtual bool OperatesOnPremultipledAlpha(PRInt32 aInput) {
    5862               0 :     return !(aInput == 1);
    5863                 :   }
    5864                 : 
    5865                 :   virtual NumberAttributesInfo GetNumberInfo();
    5866                 :   virtual EnumAttributesInfo GetEnumInfo();
    5867                 :   virtual StringAttributesInfo GetStringInfo();
    5868                 : 
    5869                 :   enum { SCALE };
    5870                 :   nsSVGNumber2 mNumberAttributes[1];
    5871                 :   static NumberInfo sNumberInfo[1];
    5872                 : 
    5873                 :   enum { CHANNEL_X, CHANNEL_Y };
    5874                 :   nsSVGEnum mEnumAttributes[2];
    5875                 :   static nsSVGEnumMapping sChannelMap[];
    5876                 :   static EnumInfo sEnumInfo[2];
    5877                 : 
    5878                 :   enum { RESULT, IN1, IN2 };
    5879                 :   nsSVGString mStringAttributes[3];
    5880                 :   static StringInfo sStringInfo[3];
    5881                 : };
    5882                 : 
    5883                 : nsSVGElement::NumberInfo nsSVGFEDisplacementMapElement::sNumberInfo[1] =
    5884                 : {
    5885                 :   { &nsGkAtoms::scale, 0, false },
    5886                 : };
    5887                 : 
    5888                 : nsSVGEnumMapping nsSVGFEDisplacementMapElement::sChannelMap[] = {
    5889                 :   {&nsGkAtoms::R, nsSVGFEDisplacementMapElement::SVG_CHANNEL_R},
    5890                 :   {&nsGkAtoms::G, nsSVGFEDisplacementMapElement::SVG_CHANNEL_G},
    5891                 :   {&nsGkAtoms::B, nsSVGFEDisplacementMapElement::SVG_CHANNEL_B},
    5892                 :   {&nsGkAtoms::A, nsSVGFEDisplacementMapElement::SVG_CHANNEL_A},
    5893                 :   {nsnull, 0}
    5894                 : };
    5895                 : 
    5896                 : nsSVGElement::EnumInfo nsSVGFEDisplacementMapElement::sEnumInfo[2] =
    5897                 : {
    5898                 :   { &nsGkAtoms::xChannelSelector,
    5899                 :     sChannelMap,
    5900                 :     nsSVGFEDisplacementMapElement::SVG_CHANNEL_A
    5901                 :   },
    5902                 :   { &nsGkAtoms::yChannelSelector,
    5903                 :     sChannelMap,
    5904                 :     nsSVGFEDisplacementMapElement::SVG_CHANNEL_A
    5905                 :   }
    5906                 : };
    5907                 : 
    5908                 : nsSVGElement::StringInfo nsSVGFEDisplacementMapElement::sStringInfo[3] =
    5909                 : {
    5910                 :   { &nsGkAtoms::result, kNameSpaceID_None, true },
    5911                 :   { &nsGkAtoms::in, kNameSpaceID_None, true },
    5912                 :   { &nsGkAtoms::in2, kNameSpaceID_None, true }
    5913                 : };
    5914                 : 
    5915               0 : NS_IMPL_NS_NEW_SVG_ELEMENT(FEDisplacementMap)
    5916                 : 
    5917                 : //----------------------------------------------------------------------
    5918                 : // nsISupports methods
    5919                 : 
    5920               0 : NS_IMPL_ADDREF_INHERITED(nsSVGFEDisplacementMapElement,nsSVGFEDisplacementMapElementBase)
    5921               0 : NS_IMPL_RELEASE_INHERITED(nsSVGFEDisplacementMapElement,nsSVGFEDisplacementMapElementBase)
    5922                 : 
    5923               0 : DOMCI_NODE_DATA(SVGFEDisplacementMapElement, nsSVGFEDisplacementMapElement)
    5924                 : 
    5925               0 : NS_INTERFACE_TABLE_HEAD(nsSVGFEDisplacementMapElement)
    5926               0 :   NS_NODE_INTERFACE_TABLE5(nsSVGFEDisplacementMapElement, nsIDOMNode,
    5927                 :                            nsIDOMElement, nsIDOMSVGElement,
    5928                 :                            nsIDOMSVGFilterPrimitiveStandardAttributes,
    5929                 :                            nsIDOMSVGFEDisplacementMapElement)
    5930               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEDisplacementMapElement)
    5931               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGFEDisplacementMapElementBase)
    5932                 : 
    5933                 : //----------------------------------------------------------------------
    5934                 : // nsIDOMNode methods
    5935                 : 
    5936               0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEDisplacementMapElement)
    5937                 : 
    5938                 : //----------------------------------------------------------------------
    5939                 : // nsIDOMSVGFEDisplacementMapElement methods
    5940                 : 
    5941                 : /* readonly attribute nsIDOMSVGAnimatedString in1; */
    5942               0 : NS_IMETHODIMP nsSVGFEDisplacementMapElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
    5943                 : {
    5944               0 :   return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
    5945                 : }
    5946                 : 
    5947                 : /* readonly attribute nsIDOMSVGAnimatedString in2; */
    5948               0 : NS_IMETHODIMP nsSVGFEDisplacementMapElement::GetIn2(nsIDOMSVGAnimatedString * *aIn)
    5949                 : {
    5950               0 :   return mStringAttributes[IN2].ToDOMAnimatedString(aIn, this);
    5951                 : }
    5952                 : 
    5953                 : /* readonly attribute nsIDOMSVGAnimatedNumber scale; */
    5954               0 : NS_IMETHODIMP nsSVGFEDisplacementMapElement::GetScale(nsIDOMSVGAnimatedNumber * *aScale)
    5955                 : {
    5956               0 :   return mNumberAttributes[SCALE].ToDOMAnimatedNumber(aScale, this);
    5957                 : }
    5958                 : 
    5959                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration xChannelSelector; */
    5960               0 : NS_IMETHODIMP nsSVGFEDisplacementMapElement::GetXChannelSelector(nsIDOMSVGAnimatedEnumeration * *aChannel)
    5961                 : {
    5962               0 :   return mEnumAttributes[CHANNEL_X].ToDOMAnimatedEnum(aChannel, this);
    5963                 : }
    5964                 : 
    5965                 : /* readonly attribute nsIDOMSVGAnimatedEnumeration yChannelSelector; */
    5966               0 : NS_IMETHODIMP nsSVGFEDisplacementMapElement::GetYChannelSelector(nsIDOMSVGAnimatedEnumeration * *aChannel)
    5967                 : {
    5968               0 :   return mEnumAttributes[CHANNEL_Y].ToDOMAnimatedEnum(aChannel, this);
    5969                 : }
    5970                 : 
    5971                 : nsresult
    5972               0 : nsSVGFEDisplacementMapElement::Filter(nsSVGFilterInstance *instance,
    5973                 :                                       const nsTArray<const Image*>& aSources,
    5974                 :                                       const Image* aTarget,
    5975                 :                                       const nsIntRect& rect)
    5976                 : {
    5977                 :   float scale = instance->GetPrimitiveNumber(nsSVGUtils::XY,
    5978               0 :                                              &mNumberAttributes[SCALE]);
    5979               0 :   if (scale == 0.0f) {
    5980               0 :     CopyRect(aTarget, aSources[0], rect);
    5981               0 :     return NS_OK;
    5982                 :   }
    5983                 : 
    5984               0 :   PRInt32 width = instance->GetSurfaceWidth();
    5985               0 :   PRInt32 height = instance->GetSurfaceHeight();
    5986                 : 
    5987               0 :   PRUint8* sourceData = aSources[0]->mImage->Data();
    5988               0 :   PRUint8* displacementData = aSources[1]->mImage->Data();
    5989               0 :   PRUint8* targetData = aTarget->mImage->Data();
    5990               0 :   PRUint32 stride = aTarget->mImage->Stride();
    5991                 : 
    5992                 :   static const PRUint16 channelMap[5] = {
    5993                 :                              0,
    5994                 :                              GFX_ARGB32_OFFSET_R,
    5995                 :                              GFX_ARGB32_OFFSET_G,
    5996                 :                              GFX_ARGB32_OFFSET_B,
    5997                 :                              GFX_ARGB32_OFFSET_A };
    5998               0 :   PRUint16 xChannel = channelMap[mEnumAttributes[CHANNEL_X].GetAnimValue()];
    5999               0 :   PRUint16 yChannel = channelMap[mEnumAttributes[CHANNEL_Y].GetAnimValue()];
    6000                 : 
    6001               0 :   double scaleOver255 = scale / 255.0;
    6002               0 :   double scaleAdjustment = 0.5 - 0.5 * scale;
    6003                 : 
    6004               0 :   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
    6005               0 :     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
    6006               0 :       PRUint32 targIndex = y * stride + 4 * x;
    6007                 :       // At some point we might want to replace this with a bilinear sample.
    6008                 :       PRInt32 sourceX = x +
    6009               0 :         NSToIntFloor(scaleOver255 * displacementData[targIndex + xChannel] +
    6010               0 :                 scaleAdjustment);
    6011                 :       PRInt32 sourceY = y +
    6012               0 :         NSToIntFloor(scaleOver255 * displacementData[targIndex + yChannel] +
    6013               0 :                 scaleAdjustment);
    6014               0 :       if (sourceX < 0 || sourceX >= width ||
    6015                 :           sourceY < 0 || sourceY >= height) {
    6016               0 :         *(PRUint32*)(targetData + targIndex) = 0;
    6017                 :       } else {
    6018                 :         *(PRUint32*)(targetData + targIndex) =
    6019               0 :           *(PRUint32*)(sourceData + sourceY * stride + 4 * sourceX);
    6020                 :       }
    6021                 :     }
    6022                 :   }
    6023               0 :   return NS_OK;
    6024                 : }
    6025                 : 
    6026                 : bool
    6027               0 : nsSVGFEDisplacementMapElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
    6028                 :                                                          nsIAtom* aAttribute) const
    6029                 : {
    6030               0 :   return nsSVGFEDisplacementMapElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
    6031                 :          (aNameSpaceID == kNameSpaceID_None &&
    6032                 :           (aAttribute == nsGkAtoms::in ||
    6033                 :            aAttribute == nsGkAtoms::in2 ||
    6034                 :            aAttribute == nsGkAtoms::scale ||
    6035                 :            aAttribute == nsGkAtoms::xChannelSelector ||
    6036               0 :            aAttribute == nsGkAtoms::yChannelSelector));
    6037                 : }
    6038                 : 
    6039                 : void
    6040               0 : nsSVGFEDisplacementMapElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
    6041                 : {
    6042               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
    6043               0 :   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
    6044               0 : }
    6045                 : 
    6046                 : nsIntRect
    6047               0 : nsSVGFEDisplacementMapElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
    6048                 :           const nsSVGFilterInstance& aInstance)
    6049                 : {
    6050                 :   // XXX we could do something clever here involving analysis of 'scale'
    6051                 :   // to figure out the maximum displacement, and then return mIn1's bounds
    6052                 :   // adjusted for the maximum displacement
    6053               0 :   return GetMaxRect();
    6054                 : }
    6055                 : 
    6056                 : void
    6057               0 : nsSVGFEDisplacementMapElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
    6058                 :           nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
    6059                 : {
    6060                 :   // in2 contains the displacements, which we read for each target pixel
    6061               0 :   aSourceBBoxes[1] = aTargetBBox;
    6062                 :   // XXX to figure out which parts of 'in' we might read, we could
    6063                 :   // do some analysis of 'scale' to figure out the maximum displacement.
    6064                 :   // For now, just leave aSourceBBoxes[0] alone, i.e. assume we use its
    6065                 :   // entire output bounding box.
    6066                 :   // If we change this, we need to change coordinate assumptions above
    6067               0 : }
    6068                 : 
    6069                 : nsIntRect
    6070               0 : nsSVGFEDisplacementMapElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
    6071                 :                                                  const nsSVGFilterInstance& aInstance)
    6072                 : {
    6073                 :   // XXX we could do something clever here involving analysis of 'scale'
    6074                 :   // to figure out the maximum displacement
    6075               0 :   return GetMaxRect();
    6076                 : }
    6077                 : 
    6078                 : //----------------------------------------------------------------------
    6079                 : // nsSVGElement methods
    6080                 : 
    6081                 : nsSVGElement::NumberAttributesInfo
    6082               0 : nsSVGFEDisplacementMapElement::GetNumberInfo()
    6083                 : {
    6084                 :   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
    6085               0 :                               ArrayLength(sNumberInfo));
    6086                 : }
    6087                 : 
    6088                 : nsSVGElement::EnumAttributesInfo
    6089               0 : nsSVGFEDisplacementMapElement::GetEnumInfo()
    6090                 : {
    6091                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    6092               0 :                             ArrayLength(sEnumInfo));
    6093                 : }
    6094                 : 
    6095                 : nsSVGElement::StringAttributesInfo
    6096               0 : nsSVGFEDisplacementMapElement::GetStringInfo()
    6097                 : {
    6098                 :   return StringAttributesInfo(mStringAttributes, sStringInfo,
    6099               0 :                               ArrayLength(sStringInfo));
    6100                 : }

Generated by: LCOV version 1.7