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
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/
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
15 * The Original Code is the Mozilla SVG project.
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.
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.
35 * ***** END LICENSE BLOCK ***** */
40 // include math.h to pick up definition of M_PI if the platform defines it
41 #define _USE_MATH_DEFINES
47 #include "gfxContext.h"
48 #include "nsIRenderingContext.h"
57 struct nsStyleSVGPaint
;
58 class nsIDOMSVGElement
;
59 class nsIDOMSVGLength
;
60 class nsIDOMSVGMatrix
;
62 class nsSVGOuterSVGFrame
;
64 class nsIDOMSVGAnimatedPreserveAspectRatio
;
68 class nsSVGSVGElement
;
73 class gfxImageSurface
;
80 class nsISVGChildFrame
;
83 #define M_PI 3.14159265358979323846
86 // SVG Frame state bits
87 #define NS_STATE_IS_OUTER_SVG 0x00100000
89 #define NS_STATE_SVG_DIRTY 0x00200000
91 /* are we the child of a non-display container? */
92 #define NS_STATE_SVG_NONDISPLAY_CHILD 0x00400000
94 #define NS_STATE_SVG_PROPAGATE_TRANSFORM 0x00800000
97 * Byte offsets of channels in a native packed gfxColor or cairo image surface.
100 #define GFX_ARGB32_OFFSET_A 0
101 #define GFX_ARGB32_OFFSET_R 1
102 #define GFX_ARGB32_OFFSET_G 2
103 #define GFX_ARGB32_OFFSET_B 3
105 #define GFX_ARGB32_OFFSET_A 3
106 #define GFX_ARGB32_OFFSET_R 2
107 #define GFX_ARGB32_OFFSET_G 1
108 #define GFX_ARGB32_OFFSET_B 0
111 // maximum dimension of an offscreen surface - choose so that
112 // the surface size doesn't overflow a 32-bit signed int using
113 // 4 bytes per pixel; in line with gfxASurface::CheckSurfaceSize
114 #define NS_SVG_OFFSCREEN_MAX_DIMENSION 16384
117 * Checks the svg enable preference and if a renderer could
118 * successfully be created. Declared as a function instead of a
119 * nsSVGUtil method so that files that can't pull in nsSVGUtils.h (due
120 * to cairo.h usage) can still query this information.
122 PRBool
NS_SVGEnabled();
124 // GRRR WINDOWS HATE HATE HATE
127 class nsSVGRenderState
130 enum RenderMode
{ NORMAL
, CLIP
, CLIP_MASK
};
133 * Render SVG to a legacy rendering context
135 nsSVGRenderState(nsIRenderingContext
*aContext
);
137 * Render SVG to a temporary surface
139 nsSVGRenderState(gfxASurface
*aSurface
);
141 nsIRenderingContext
*GetRenderingContext(nsIFrame
*aFrame
);
142 gfxContext
*GetGfxContext() { return mGfxContext
; }
144 void SetRenderMode(RenderMode aMode
) { mRenderMode
= aMode
; }
145 RenderMode
GetRenderMode() { return mRenderMode
; }
148 RenderMode mRenderMode
;
149 nsCOMPtr
<nsIRenderingContext
> mRenderingContext
;
150 nsRefPtr
<gfxContext
> mGfxContext
;
153 class nsAutoSVGRenderMode
156 nsAutoSVGRenderMode(nsSVGRenderState
*aState
,
157 nsSVGRenderState::RenderMode aMode
) : mState(aState
) {
158 mOriginalMode
= aState
->GetRenderMode();
159 aState
->SetRenderMode(aMode
);
161 ~nsAutoSVGRenderMode() { mState
->SetRenderMode(mOriginalMode
); }
164 nsSVGRenderState
*mState
;
165 nsSVGRenderState::RenderMode mOriginalMode
;
168 #define NS_ISVGFILTERPROPERTY_IID \
169 { 0x9744ee20, 0x1bcf, 0x4c62, \
170 { 0x86, 0x7d, 0xd3, 0x7a, 0x91, 0x60, 0x3e, 0xef } }
172 class nsISVGFilterProperty
: public nsISupports
175 NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGFILTERPROPERTY_IID
)
176 virtual void Invalidate() = 0;
179 NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGFilterProperty
, NS_ISVGFILTERPROPERTY_IID
)
185 * Get a font-size (em) of an nsIContent
187 static float GetFontSize(nsIContent
*aContent
);
188 static float GetFontSize(nsIFrame
*aFrame
);
190 * Get an x-height of of an nsIContent
192 static float GetFontXHeight(nsIContent
*aContent
);
193 static float GetFontXHeight(nsIFrame
*aFrame
);
196 * Converts image data from premultipled to unpremultiplied alpha
198 static void UnPremultiplyImageDataAlpha(PRUint8
*data
,
200 const nsIntRect
&rect
);
202 * Converts image data from unpremultipled to premultiplied alpha
204 static void PremultiplyImageDataAlpha(PRUint8
*data
,
206 const nsIntRect
&rect
);
208 * Converts image data from premultiplied sRGB to Linear RGB
210 static void ConvertImageDataToLinearRGB(PRUint8
*data
,
212 const nsIntRect
&rect
);
214 * Converts image data from LinearRGB to premultiplied sRGB
216 static void ConvertImageDataFromLinearRGB(PRUint8
*data
,
218 const nsIntRect
&rect
);
221 * Report a localized error message to the error console.
223 static nsresult
ReportToConsole(nsIDocument
* doc
,
224 const char* aWarning
,
225 const PRUnichar
**aParams
,
226 PRUint32 aParamsLength
);
229 * Converts a nsStyleCoord into a userspace value. Handles units
230 * Factor (straight userspace), Coord (dimensioned), and Percent (of
231 * the current SVG viewport)
233 static float CoordToFloat(nsPresContext
*aPresContext
,
234 nsSVGElement
*aContent
,
235 const nsStyleCoord
&aCoord
);
237 * Return the nearest viewport element
239 static nsresult
GetNearestViewportElement(nsIContent
*aContent
,
240 nsIDOMSVGElement
* *aNearestViewportElement
);
243 * Get the farthest viewport element
245 static nsresult
GetFarthestViewportElement(nsIContent
*aContent
,
246 nsIDOMSVGElement
* *aFarthestViewportElement
);
249 * Creates a bounding box by walking the children and doing union.
251 static nsresult
GetBBox(nsFrameList
*aFrames
, nsIDOMSVGRect
**_retval
);
254 * Figures out the worst case invalidation area for a frame, taking
255 * filters into account.
256 * @param aRect the area in app units that needs to be invalidated in aFrame
257 * @return the rect in app units that should be invalidated, taking
258 * filters into account. Will return aRect when no filters are present.
260 static nsRect
FindFilterInvalidation(nsIFrame
*aFrame
, const nsRect
& aRect
);
263 * Invalidates the area covered by the frame
265 static void InvalidateCoveredRegion(nsIFrame
*aFrame
);
268 * Update the area covered by the frame
270 static void UpdateGraphic(nsISVGChildFrame
*aSVGFrame
);
273 * Update the filter invalidation region for ancestor frames, if relevant.
275 static void NotifyAncestorsOfFilterRegionChange(nsIFrame
*aFrame
);
277 /* enum for specifying coordinate direction for ObjectSpace/UserSpace */
278 enum ctxDirection
{ X
, Y
, XY
};
281 * Computes sqrt((aWidth^2 + aHeight^2)/2);
283 static double ComputeNormalizedHypotenuse(double aWidth
, double aHeight
);
285 /* Computes the input length in terms of object space coordinates.
286 Input: rect - bounding box
287 length - length to be converted
289 static float ObjectSpace(nsIDOMSVGRect
*aRect
, const nsSVGLength2
*aLength
);
291 /* Computes the input length in terms of user space coordinates.
292 Input: content - object to be used for determining user space
293 Input: length - length to be converted
295 static float UserSpace(nsSVGElement
*aSVGElement
, const nsSVGLength2
*aLength
);
297 /* Computes the input length in terms of user space coordinates.
298 Input: aFrame - object to be used for determining user space
299 length - length to be converted
301 static float UserSpace(nsIFrame
*aFrame
, const nsSVGLength2
*aLength
);
303 /* Tranforms point by the matrix. In/out: x,y */
305 TransformPoint(nsIDOMSVGMatrix
*matrix
,
308 /* Returns the angle halfway between the two specified angles */
310 AngleBisect(float a1
, float a2
);
312 /* Find the outermost SVG frame of the passed frame */
313 static nsSVGOuterSVGFrame
*
314 GetOuterSVGFrame(nsIFrame
*aFrame
);
317 * Get the covered region for a frame. Return null if it's not an SVG frame.
318 * @param aRect gets a rectangle in app units
319 * @return the outer SVG frame which aRect is relative to
322 GetOuterSVGFrameAndCoveredRegion(nsIFrame
* aFrame
, nsRect
* aRect
);
324 /* Generate a viewbox to viewport tranformation matrix */
326 static already_AddRefed
<nsIDOMSVGMatrix
>
327 GetViewBoxTransform(float aViewportWidth
, float aViewportHeight
,
328 float aViewboxX
, float aViewboxY
,
329 float aViewboxWidth
, float aViewboxHeight
,
330 nsIDOMSVGAnimatedPreserveAspectRatio
*aPreserveAspectRatio
,
331 PRBool aIgnoreAlign
= PR_FALSE
);
333 /* Paint SVG frame with SVG effects - aDirtyRect is the area being
334 * redrawn, in device pixel coordinates relative to the outer svg */
336 PaintFrameWithEffects(nsSVGRenderState
*aContext
,
337 const nsIntRect
*aDirtyRect
,
340 /* Hit testing - check if point hits the clipPath of indicated
341 * frame. Returns true if no clipPath set. */
343 HitTestClip(nsIFrame
*aFrame
, const nsPoint
&aPoint
);
345 /* Hit testing - check if point hits any children of frame. */
348 HitTestChildren(nsIFrame
*aFrame
, const nsPoint
&aPoint
);
350 /* Add observation of an nsISVGValue to an nsISVGValueObserver */
352 AddObserver(nsISupports
*aObserver
, nsISupports
*aTarget
);
354 /* Remove observation of an nsISVGValue from an nsISVGValueObserver */
356 RemoveObserver(nsISupports
*aObserver
, nsISupports
*aTarget
);
359 * Returns the CanvasTM of the indicated frame, whether it's a
360 * child SVG frame, container SVG frame, or a regular frame.
361 * For regular frames, we just return an identity matrix.
363 static already_AddRefed
<nsIDOMSVGMatrix
> GetCanvasTM(nsIFrame
*aFrame
);
366 * Tells child frames that something that might affect them has changed
369 NotifyChildrenOfSVGChange(nsIFrame
*aFrame
, PRUint32 aFlags
);
372 * Get frame's covered region by walking the children and doing union.
375 GetCoveredRegion(const nsFrameList
&aFrames
);
378 * Convert a rect from device pixel units to app pixel units by inflation.
381 ToAppPixelRect(nsPresContext
*aPresContext
,
382 double xmin
, double ymin
, double xmax
, double ymax
);
384 ToAppPixelRect(nsPresContext
*aPresContext
, const gfxRect
& rect
);
387 * Convert a surface size to an integer for use by thebes
388 * possibly making it smaller in the process so the surface does not
389 * use excessive memory.
390 * @param aSize the desired surface size
391 * @param aResultOverflows true if the desired surface size is too big
392 * @return the surface size to use
395 ConvertToSurfaceSize(const gfxSize
& aSize
, PRBool
*aResultOverflows
);
398 * Get a pointer to a surface that can be used to create thebes
399 * contexts for various measurement purposes.
402 GetThebesComputationalSurface();
405 * Convert a nsIDOMSVGMatrix to a gfxMatrix.
408 ConvertSVGMatrixToThebes(nsIDOMSVGMatrix
*aMatrix
);
411 * Hit test a given rectangle/matrix.
414 HitTestRect(nsIDOMSVGMatrix
*aMatrix
,
415 float aRX
, float aRY
, float aRWidth
, float aRHeight
,
419 static void CompositeSurfaceMatrix(gfxContext
*aContext
,
420 gfxASurface
*aSurface
,
421 nsIDOMSVGMatrix
*aCTM
, float aOpacity
);
423 static void CompositePatternMatrix(gfxContext
*aContext
,
424 gfxPattern
*aPattern
,
425 nsIDOMSVGMatrix
*aCTM
, float aWidth
, float aHeight
, float aOpacity
);
427 static void SetClipRect(gfxContext
*aContext
,
428 nsIDOMSVGMatrix
*aCTM
, float aX
, float aY
,
429 float aWidth
, float aHeight
);
432 * If aIn can be represented exactly using an nsIntRect (i.e. integer-aligned edges and
433 * coordinates in the PRInt32 range) then we set aOut to that rectangle, otherwise
436 static nsresult
GfxRectToIntRect(const gfxRect
& aIn
, nsIntRect
* aOut
);
439 * Restricts aRect to pixels that intersect aGfxRect.
441 static void ClipToGfxRect(nsIntRect
* aRect
, const gfxRect
& aGfxRect
);
443 /* Using group opacity instead of fill or stroke opacity on a
444 * geometry object seems to be a common authoring mistake. If we're
445 * not applying filters and not both stroking and filling, we can
446 * generate the same result without going through the overhead of a
449 CanOptimizeOpacity(nsIFrame
*aFrame
);
451 /* Calculate the maximum expansion of a matrix */
453 MaxExpansion(nsIDOMSVGMatrix
*aMatrix
);
455 /* Take a CTM and adjust for object bounding box coordinates, if needed */
456 static already_AddRefed
<nsIDOMSVGMatrix
>
457 AdjustMatrixForUnits(nsIDOMSVGMatrix
*aMatrix
,
462 * Get bounding-box for aFrame. Matrix propagation is disabled so the
463 * bounding box is computed in terms of aFrame's own user space.
465 static already_AddRefed
<nsIDOMSVGRect
>
466 GetBBox(nsIFrame
*aFrame
);
468 * Compute a rectangle in userSpaceOnUse or objectBoundingBoxUnits.
469 * @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing
470 * the x, y, width and height values in that order
471 * @param aBBox the bounding box of the object the rect is relative to;
472 * may be null if aUnits is not SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
473 * @param aFrame the object in which to interpret user-space units;
474 * may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
477 GetRelativeRect(PRUint16 aUnits
, const nsSVGLength2
*aXYWH
, nsIDOMSVGRect
*aBBox
,
482 WritePPM(const char *fname
, gfxImageSurface
*aSurface
);
486 /* Computational (nil) surfaces */
487 static gfxASurface
*mThebesComputationalSurface
;