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 : #ifndef __NS_SVGFILTERSELEMENT_H__
38 : #define __NS_SVGFILTERSELEMENT_H__
39 :
40 : #include "gfxImageSurface.h"
41 : #include "gfxRect.h"
42 : #include "nsIDOMSVGFilters.h"
43 : #include "nsIDOMSVGURIReference.h"
44 : #include "nsIFrame.h"
45 : #include "nsImageLoadingContent.h"
46 : #include "nsSVGLength2.h"
47 : #include "nsSVGString.h"
48 : #include "nsSVGStylableElement.h"
49 : #include "SVGAnimatedPreserveAspectRatio.h"
50 :
51 : class nsSVGFilterInstance;
52 : class nsSVGFilterResource;
53 : class nsSVGNumberPair;
54 :
55 0 : struct nsSVGStringInfo {
56 0 : nsSVGStringInfo(const nsSVGString* aString,
57 : nsSVGElement *aElement) :
58 0 : mString(aString), mElement(aElement) {}
59 :
60 : const nsSVGString* mString;
61 : nsSVGElement* mElement;
62 : };
63 :
64 : typedef nsSVGStylableElement nsSVGFEBase;
65 :
66 : #define NS_SVG_FE_CID \
67 : { 0x60483958, 0xd229, 0x4a77, \
68 : { 0x96, 0xb2, 0x62, 0x3e, 0x69, 0x95, 0x1e, 0x0e } }
69 :
70 : /**
71 : * Base class for filter primitive elements
72 : * Children of those elements e.g. feMergeNode
73 : * derive from SVGFEUnstyledElement instead
74 : */
75 : class nsSVGFE : public nsSVGFEBase
76 : //, public nsIDOMSVGFilterPrimitiveStandardAttributes
77 0 : {
78 : friend class nsSVGFilterInstance;
79 :
80 : public:
81 : class ColorModel {
82 : public:
83 : enum ColorSpace { SRGB, LINEAR_RGB };
84 : enum AlphaChannel { UNPREMULTIPLIED, PREMULTIPLIED };
85 :
86 0 : ColorModel(ColorSpace aColorSpace, AlphaChannel aAlphaChannel) :
87 0 : mColorSpace(aColorSpace), mAlphaChannel(aAlphaChannel) {}
88 0 : ColorModel() :
89 0 : mColorSpace(SRGB), mAlphaChannel(PREMULTIPLIED) {}
90 0 : bool operator==(const ColorModel& aOther) const {
91 : return mColorSpace == aOther.mColorSpace &&
92 0 : mAlphaChannel == aOther.mAlphaChannel;
93 : }
94 : ColorSpace mColorSpace;
95 : AlphaChannel mAlphaChannel;
96 : };
97 :
98 0 : struct Image {
99 : // The device offset of mImage makes it relative to filter space
100 : nsRefPtr<gfxImageSurface> mImage;
101 : // The filter primitive subregion bounding this image, in filter space
102 : gfxRect mFilterPrimitiveSubregion;
103 : ColorModel mColorModel;
104 : // When true, the RGB values are the same for all pixels in mImage
105 : bool mConstantColorChannels;
106 :
107 0 : Image() : mConstantColorChannels(false) {}
108 : };
109 :
110 : protected:
111 0 : nsSVGFE(already_AddRefed<nsINodeInfo> aNodeInfo) : nsSVGFEBase(aNodeInfo) {}
112 :
113 0 : struct ScaleInfo {
114 : nsRefPtr<gfxImageSurface> mRealTarget;
115 : nsRefPtr<gfxImageSurface> mSource;
116 : nsRefPtr<gfxImageSurface> mTarget;
117 : nsIntRect mDataRect; // rect in mSource and mTarget to operate on
118 : bool mRescaling;
119 : };
120 :
121 : ScaleInfo SetupScalingFilter(nsSVGFilterInstance *aInstance,
122 : const Image *aSource,
123 : const Image *aTarget,
124 : const nsIntRect& aDataRect,
125 : nsSVGNumberPair *aUnit);
126 :
127 : void FinishScalingFilter(ScaleInfo *aScaleInfo);
128 :
129 : public:
130 : ColorModel
131 0 : GetInputColorModel(nsSVGFilterInstance* aInstance, PRInt32 aInputIndex,
132 : Image* aImage) {
133 : return ColorModel(
134 0 : (OperatesOnSRGB(aInstance, aInputIndex, aImage) ?
135 : ColorModel::SRGB : ColorModel::LINEAR_RGB),
136 0 : (OperatesOnPremultipledAlpha(aInputIndex) ?
137 0 : ColorModel::PREMULTIPLIED : ColorModel::UNPREMULTIPLIED));
138 : }
139 :
140 : ColorModel
141 0 : GetOutputColorModel(nsSVGFilterInstance* aInstance) {
142 : return ColorModel(
143 0 : (OperatesOnSRGB(aInstance, -1, nsnull) ?
144 : ColorModel::SRGB : ColorModel::LINEAR_RGB),
145 0 : (OperatesOnPremultipledAlpha(-1) ?
146 0 : ColorModel::PREMULTIPLIED : ColorModel::UNPREMULTIPLIED));
147 : }
148 :
149 : // See http://www.w3.org/TR/SVG/filters.html#FilterPrimitiveSubRegion
150 0 : virtual bool SubregionIsUnionOfRegions() { return true; }
151 :
152 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_CID)
153 :
154 : // interfaces:
155 : NS_DECL_ISUPPORTS_INHERITED
156 : NS_DECL_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES
157 :
158 : // nsIContent interface
159 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
160 :
161 : // nsSVGElement interface
162 : virtual bool HasValidDimensions() const;
163 :
164 : virtual nsSVGString& GetResultImageName() = 0;
165 : // Return a list of all image names used as sources. Default is to
166 : // return no sources.
167 : virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources);
168 : // Compute the bounding box of the filter output. The default is just the
169 : // union of the source bounding boxes. The caller is
170 : // responsible for clipping this to the filter primitive subregion, so
171 : // if the filter fills its filter primitive subregion, it can just
172 : // return GetMaxRect() here.
173 : // The source bounding boxes are ordered corresponding to GetSourceImageNames.
174 : virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
175 : const nsSVGFilterInstance& aInstance);
176 : // Given a bounding box for what we need to compute in the target,
177 : // compute which regions of the inputs are needed. On input
178 : // aSourceBBoxes contains the bounding box of what's rendered by
179 : // each source; this function should change those boxes to indicate
180 : // which region of the source's output it needs.
181 : // The default implementation sets all the source bboxes to the
182 : // target bbox.
183 : virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
184 : nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
185 : // Given the bounding boxes for the pixels that have changed in the inputs,
186 : // compute the bounding box of the changes in this primitive's output.
187 : // The result will be clipped by the caller to the result of ComputeTargetBBox
188 : // since there's no way anything outside that can change.
189 : // The default implementation returns the union of the source change boxes.
190 : virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes,
191 : const nsSVGFilterInstance& aInstance);
192 :
193 : // Perform the actual filter operation.
194 : // We guarantee that every mImage from aSources and aTarget has the
195 : // same width, height, stride and device offset.
196 : // aTarget is already filled in. This function just needs to fill in the
197 : // pixels of aTarget->mImage (which have already been cleared).
198 : // @param aDataRect the destination rectangle that needs to be painted,
199 : // relative to aTarget's surface data. This is the intersection of the
200 : // filter primitive subregion for this filter element and the
201 : // temporary surface area. Output need not be clipped to this rect but
202 : // it must be clipped to aTarget->mFilterPrimitiveSubregion.
203 : virtual nsresult Filter(nsSVGFilterInstance* aInstance,
204 : const nsTArray<const Image*>& aSources,
205 : const Image* aTarget,
206 : const nsIntRect& aDataRect) = 0;
207 :
208 : // returns true if changes to the attribute should cause us to
209 : // repaint the filter
210 : virtual bool AttributeAffectsRendering(
211 : PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
212 :
213 0 : static nsIntRect GetMaxRect() {
214 : // Try to avoid overflow errors dealing with this rect. It will
215 : // be intersected with some other reasonable-sized rect eventually.
216 0 : return nsIntRect(PR_INT32_MIN/2, PR_INT32_MIN/2, PR_INT32_MAX, PR_INT32_MAX);
217 : }
218 :
219 : operator nsISupports*() { return static_cast<nsIContent*>(this); }
220 :
221 : protected:
222 0 : virtual bool OperatesOnPremultipledAlpha(PRInt32) { return true; }
223 :
224 : // Called either with aInputIndex >=0 in which case this is
225 : // testing whether the input 'aInputIndex' should be SRGB, or
226 : // if aInputIndex is -1 returns true if the output will be SRGB
227 0 : virtual bool OperatesOnSRGB(nsSVGFilterInstance* aInstance,
228 : PRInt32 aInputIndex, Image* aImage) {
229 0 : nsIFrame* frame = GetPrimaryFrame();
230 0 : if (!frame) return false;
231 :
232 0 : nsStyleContext* style = frame->GetStyleContext();
233 0 : return style->GetStyleSVG()->mColorInterpolationFilters ==
234 0 : NS_STYLE_COLOR_INTERPOLATION_SRGB;
235 : }
236 :
237 : // nsSVGElement specializations:
238 : virtual LengthAttributesInfo GetLengthInfo();
239 :
240 : // nsIDOMSVGFitlerPrimitiveStandardAttributes values
241 : enum { X, Y, WIDTH, HEIGHT };
242 : nsSVGLength2 mLengthAttributes[4];
243 : static LengthInfo sLengthInfo[4];
244 : };
245 :
246 : typedef nsSVGFE nsSVGFEImageElementBase;
247 :
248 : class nsSVGFEImageElement : public nsSVGFEImageElementBase,
249 : public nsIDOMSVGFEImageElement,
250 : public nsIDOMSVGURIReference,
251 : public nsImageLoadingContent
252 : {
253 : friend class SVGFEImageFrame;
254 :
255 : protected:
256 : friend nsresult NS_NewSVGFEImageElement(nsIContent **aResult,
257 : already_AddRefed<nsINodeInfo> aNodeInfo);
258 : nsSVGFEImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
259 : virtual ~nsSVGFEImageElement();
260 :
261 : public:
262 0 : virtual bool SubregionIsUnionOfRegions() { return false; }
263 :
264 : // interfaces:
265 : NS_DECL_ISUPPORTS_INHERITED
266 :
267 : // FE Base
268 0 : NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEImageElementBase::)
269 :
270 : virtual nsresult Filter(nsSVGFilterInstance* aInstance,
271 : const nsTArray<const Image*>& aSources,
272 : const Image* aTarget,
273 : const nsIntRect& aDataRect);
274 : virtual bool AttributeAffectsRendering(
275 : PRInt32 aNameSpaceID, nsIAtom* aAttribute) const;
276 0 : virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
277 : virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
278 : const nsSVGFilterInstance& aInstance);
279 :
280 : NS_DECL_NSIDOMSVGFEIMAGEELEMENT
281 : NS_DECL_NSIDOMSVGURIREFERENCE
282 :
283 0 : NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEImageElementBase::)
284 :
285 0 : NS_FORWARD_NSIDOMNODE(nsSVGFEImageElementBase::)
286 0 : NS_FORWARD_NSIDOMELEMENT(nsSVGFEImageElementBase::)
287 :
288 : // nsIContent
289 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
290 :
291 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
292 :
293 : virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
294 : const nsAttrValue* aValue, bool aNotify);
295 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
296 : nsIContent* aBindingParent,
297 : bool aCompileEventHandlers);
298 : virtual nsEventStates IntrinsicState() const;
299 :
300 : // imgIDecoderObserver
301 : NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
302 : const PRUnichar *statusArg);
303 : // imgIContainerObserver
304 : NS_IMETHOD FrameChanged(imgIRequest* aRequest,
305 : imgIContainer *aContainer,
306 : const nsIntRect *aDirtyRect);
307 : // imgIContainerObserver
308 : NS_IMETHOD OnStartContainer(imgIRequest *aRequest,
309 : imgIContainer *aContainer);
310 :
311 : void MaybeLoadSVGImage();
312 :
313 : virtual nsXPCClassInfo* GetClassInfo();
314 : private:
315 : // Invalidate users of the filter containing this element.
316 : void Invalidate();
317 :
318 : nsresult LoadSVGImage(bool aForce, bool aNotify);
319 :
320 : protected:
321 0 : virtual bool OperatesOnSRGB(nsSVGFilterInstance*,
322 0 : PRInt32, Image*) { return true; }
323 :
324 : virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
325 : virtual StringAttributesInfo GetStringInfo();
326 :
327 : enum { RESULT, HREF };
328 : nsSVGString mStringAttributes[2];
329 : static StringInfo sStringInfo[2];
330 :
331 : SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
332 : };
333 :
334 : typedef nsSVGElement SVGFEUnstyledElementBase;
335 :
336 : class SVGFEUnstyledElement : public SVGFEUnstyledElementBase
337 0 : {
338 : protected:
339 0 : SVGFEUnstyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
340 0 : : SVGFEUnstyledElementBase(aNodeInfo) {}
341 :
342 : public:
343 : // returns true if changes to the attribute should cause us to
344 : // repaint the filter
345 : virtual bool AttributeAffectsRendering(
346 : PRInt32 aNameSpaceID, nsIAtom* aAttribute) const = 0;
347 : };
348 :
349 : #endif
|