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, &litude,
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 : }
|