michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef NS_SVGUTILS_H michael@0: #define NS_SVGUTILS_H michael@0: michael@0: // include math.h to pick up definition of M_ maths defines e.g. M_PI michael@0: #define _USE_MATH_DEFINES michael@0: #include michael@0: michael@0: #include "DrawMode.h" michael@0: #include "gfx2DGlue.h" michael@0: #include "gfxMatrix.h" michael@0: #include "gfxPoint.h" michael@0: #include "gfxRect.h" michael@0: #include "mozilla/gfx/Rect.h" michael@0: #include "nsAlgorithm.h" michael@0: #include "nsChangeHint.h" michael@0: #include "nsColor.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsID.h" michael@0: #include "nsISupportsBase.h" michael@0: #include "nsMathUtils.h" michael@0: #include "nsStyleStruct.h" michael@0: #include "mozilla/Constants.h" michael@0: #include michael@0: michael@0: class gfxContext; michael@0: class gfxPattern; michael@0: class nsFrameList; michael@0: class nsIContent; michael@0: class nsIDocument; michael@0: class nsIFrame; michael@0: class nsPresContext; michael@0: class nsRenderingContext; michael@0: class nsStyleContext; michael@0: class nsStyleCoord; michael@0: class nsSVGDisplayContainerFrame; michael@0: class nsSVGElement; michael@0: class nsSVGEnum; michael@0: class nsSVGLength2; michael@0: class nsSVGOuterSVGFrame; michael@0: class nsSVGPathGeometryFrame; michael@0: class nsTextFrame; michael@0: class gfxTextContextPaint; michael@0: michael@0: struct nsStyleSVG; michael@0: struct nsStyleSVGPaint; michael@0: struct nsRect; michael@0: struct nsIntRect; michael@0: struct nsPoint; michael@0: michael@0: namespace mozilla { michael@0: class SVGAnimatedPreserveAspectRatio; michael@0: class SVGPreserveAspectRatio; michael@0: namespace dom { michael@0: class Element; michael@0: } // namespace dom michael@0: namespace gfx { michael@0: class SourceSurface; michael@0: } michael@0: } // namespace mozilla michael@0: michael@0: // maximum dimension of an offscreen surface - choose so that michael@0: // the surface size doesn't overflow a 32-bit signed int using michael@0: // 4 bytes per pixel; in line with gfxASurface::CheckSurfaceSize michael@0: // In fact Macs can't even manage that michael@0: #define NS_SVG_OFFSCREEN_MAX_DIMENSION 4096 michael@0: michael@0: #define SVG_HIT_TEST_FILL 0x01 michael@0: #define SVG_HIT_TEST_STROKE 0x02 michael@0: #define SVG_HIT_TEST_CHECK_MRECT 0x04 michael@0: michael@0: michael@0: bool NS_SVGDisplayListHitTestingEnabled(); michael@0: bool NS_SVGDisplayListPaintingEnabled(); michael@0: michael@0: /** michael@0: * Sometimes we need to distinguish between an empty box and a box michael@0: * that contains an element that has no size e.g. a point at the origin. michael@0: */ michael@0: class SVGBBox { michael@0: typedef mozilla::gfx::Rect Rect; michael@0: michael@0: public: michael@0: SVGBBox() michael@0: : mIsEmpty(true) {} michael@0: michael@0: SVGBBox(const Rect& aRect) michael@0: : mBBox(aRect), mIsEmpty(false) {} michael@0: michael@0: SVGBBox(const gfxRect& aRect) michael@0: : mBBox(ToRect(aRect)), mIsEmpty(false) {} michael@0: michael@0: gfxRect ToThebesRect() const { michael@0: return ThebesRect(mBBox); michael@0: } michael@0: michael@0: bool IsEmpty() const { michael@0: return mIsEmpty; michael@0: } michael@0: michael@0: void UnionEdges(const SVGBBox& aSVGBBox) { michael@0: if (aSVGBBox.mIsEmpty) { michael@0: return; michael@0: } michael@0: mBBox = mIsEmpty ? aSVGBBox.mBBox : mBBox.UnionEdges(aSVGBBox.mBBox); michael@0: mIsEmpty = false; michael@0: } michael@0: michael@0: private: michael@0: Rect mBBox; michael@0: bool mIsEmpty; michael@0: }; michael@0: michael@0: // GRRR WINDOWS HATE HATE HATE michael@0: #undef CLIP_MASK michael@0: michael@0: class MOZ_STACK_CLASS SVGAutoRenderState michael@0: { michael@0: public: michael@0: enum RenderMode { michael@0: /** michael@0: * Used to inform SVG frames that they should paint as normal. michael@0: */ michael@0: NORMAL, michael@0: /** michael@0: * Used to inform SVG frames when they are painting as the child of a michael@0: * simple clipPath. In this case they should only draw their basic geometry michael@0: * as a path. They should not fill, stroke, or paint anything else. michael@0: */ michael@0: CLIP, michael@0: /** michael@0: * Used to inform SVG frames when they are painting as the child of a michael@0: * complex clipPath that requires the use of a clip mask. In this case they michael@0: * should only draw their basic geometry as a path and then fill it using michael@0: * fully opaque white. They should not stroke, or paint anything else. michael@0: */ michael@0: CLIP_MASK michael@0: }; michael@0: michael@0: SVGAutoRenderState(nsRenderingContext *aContext, RenderMode aMode michael@0: MOZ_GUARD_OBJECT_NOTIFIER_PARAM); michael@0: ~SVGAutoRenderState(); michael@0: michael@0: void SetPaintingToWindow(bool aPaintingToWindow); michael@0: michael@0: static RenderMode GetRenderMode(nsRenderingContext *aContext); michael@0: static bool IsPaintingToWindow(nsRenderingContext *aContext); michael@0: michael@0: private: michael@0: nsRenderingContext *mContext; michael@0: void *mOriginalRenderState; michael@0: RenderMode mMode; michael@0: bool mPaintingToWindow; michael@0: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER michael@0: }; michael@0: michael@0: michael@0: #define NS_ISVGFILTERREFERENCE_IID \ michael@0: { 0x9744ee20, 0x1bcf, 0x4c62, \ michael@0: { 0x86, 0x7d, 0xd3, 0x7a, 0x91, 0x60, 0x3e, 0xef } } michael@0: michael@0: class nsISVGFilterReference : public nsISupports michael@0: { michael@0: public: michael@0: NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGFILTERREFERENCE_IID) michael@0: virtual void Invalidate() = 0; michael@0: }; michael@0: michael@0: NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGFilterReference, NS_ISVGFILTERREFERENCE_IID) michael@0: michael@0: /** michael@0: * General functions used by all of SVG layout and possibly content code. michael@0: * If a method is used by content and depends only on other content methods michael@0: * it should go in SVGContentUtils instead. michael@0: */ michael@0: class nsSVGUtils michael@0: { michael@0: public: michael@0: typedef mozilla::dom::Element Element; michael@0: michael@0: static void Init(); michael@0: michael@0: /** michael@0: * Gets the nearest nsSVGInnerSVGFrame or nsSVGOuterSVGFrame frame. aFrame michael@0: * must be an SVG frame. If aFrame is of type nsGkAtoms::svgOuterSVGFrame, michael@0: * returns nullptr. michael@0: */ michael@0: static nsSVGDisplayContainerFrame* GetNearestSVGViewport(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Returns the frame's post-filter visual overflow rect when passed the michael@0: * frame's pre-filter visual overflow rect. If the frame is not currently michael@0: * being filtered, this function simply returns aUnfilteredRect. michael@0: */ michael@0: static nsRect GetPostFilterVisualOverflowRect(nsIFrame *aFrame, michael@0: const nsRect &aUnfilteredRect); michael@0: michael@0: /** michael@0: * Schedules an update of the frame's bounds (which will in turn invalidate michael@0: * the new area that the frame should paint to). michael@0: * michael@0: * This does nothing when passed an NS_FRAME_IS_NONDISPLAY frame. michael@0: * In future we may want to allow ReflowSVG to be called on such frames, michael@0: * but that would be better implemented as a ForceReflowSVG function to michael@0: * be called synchronously while painting them without marking or paying michael@0: * attention to dirty bits like this function. michael@0: * michael@0: * This is very similar to PresShell::FrameNeedsReflow. The main reason that michael@0: * we have this function instead of using FrameNeedsReflow is because we need michael@0: * to be able to call it under nsSVGOuterSVGFrame::NotifyViewportChange when michael@0: * that function is called by nsSVGOuterSVGFrame::Reflow. FrameNeedsReflow michael@0: * is not suitable for calling during reflow though, and it asserts as much. michael@0: * The reason that we want to be callable under NotifyViewportChange is michael@0: * because we want to synchronously notify and dirty the nsSVGOuterSVGFrame's michael@0: * children so that when nsSVGOuterSVGFrame::DidReflow is called its children michael@0: * will be updated for the new size as appropriate. Otherwise we'd have to michael@0: * post an event to the event loop to mark dirty flags and request an update. michael@0: * michael@0: * Another reason that we don't currently want to call michael@0: * PresShell::FrameNeedsReflow is because passing eRestyle to it to get it to michael@0: * mark descendants dirty would cause it to descend through michael@0: * nsSVGForeignObjectFrame frames to mark their children dirty, but we want to michael@0: * handle nsSVGForeignObjectFrame specially. It would also do unnecessary work michael@0: * descending into NS_FRAME_IS_NONDISPLAY frames. michael@0: */ michael@0: static void ScheduleReflowSVG(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Returns true if the frame or any of its children need ReflowSVG michael@0: * to be called on them. michael@0: */ michael@0: static bool NeedsReflowSVG(nsIFrame *aFrame); michael@0: michael@0: /* michael@0: * Update the filter invalidation region for ancestor frames, if relevant. michael@0: */ michael@0: static void NotifyAncestorsOfFilterRegionChange(nsIFrame *aFrame); michael@0: michael@0: /* Computes the input length in terms of object space coordinates. michael@0: Input: rect - bounding box michael@0: length - length to be converted michael@0: */ michael@0: static float ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength); michael@0: michael@0: /* Computes the input length in terms of user space coordinates. michael@0: Input: content - object to be used for determining user space michael@0: Input: length - length to be converted michael@0: */ michael@0: static float UserSpace(nsSVGElement *aSVGElement, const nsSVGLength2 *aLength); michael@0: michael@0: /* Computes the input length in terms of user space coordinates. michael@0: Input: aFrame - object to be used for determining user space michael@0: length - length to be converted michael@0: */ michael@0: static float UserSpace(nsIFrame *aFrame, const nsSVGLength2 *aLength); michael@0: michael@0: /* Find the outermost SVG frame of the passed frame */ michael@0: static nsSVGOuterSVGFrame * michael@0: GetOuterSVGFrame(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Get the covered region for a frame. Return null if it's not an SVG frame. michael@0: * @param aRect gets a rectangle in app units michael@0: * @return the outer SVG frame which aRect is relative to michael@0: */ michael@0: static nsIFrame* michael@0: GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame, nsRect* aRect); michael@0: michael@0: /* Paint SVG frame with SVG effects - aDirtyRect is the area being michael@0: * redrawn, in device pixel coordinates relative to the outer svg */ michael@0: static void michael@0: PaintFrameWithEffects(nsRenderingContext *aContext, michael@0: const nsIntRect *aDirtyRect, michael@0: nsIFrame *aFrame, michael@0: nsIFrame* aTransformRoot = nullptr); michael@0: michael@0: /* Hit testing - check if point hits the clipPath of indicated michael@0: * frame. Returns true if no clipPath set. */ michael@0: static bool michael@0: HitTestClip(nsIFrame *aFrame, const nsPoint &aPoint); michael@0: michael@0: /* Hit testing - check if point hits any children of frame. */ michael@0: michael@0: static nsIFrame * michael@0: HitTestChildren(nsIFrame *aFrame, const nsPoint &aPoint); michael@0: michael@0: /* michael@0: * Returns the CanvasTM of the indicated frame, whether it's a michael@0: * child SVG frame, container SVG frame, or a regular frame. michael@0: * For regular frames, we just return an identity matrix. michael@0: */ michael@0: static gfxMatrix GetCanvasTM(nsIFrame* aFrame, uint32_t aFor, michael@0: nsIFrame* aTransformRoot = nullptr); michael@0: michael@0: /** michael@0: * Returns the transform from aFrame's user space to canvas space. Only call michael@0: * with SVG frames. This is like GetCanvasTM, except that it only includes michael@0: * the transforms from aFrame's user space (i.e. the coordinate context michael@0: * established by its 'transform' attribute, or else the coordinate context michael@0: * that its _parent_ establishes for its children) to outer- device michael@0: * space. Specifically, it does not include any other transforms introduced michael@0: * by the frame such as x/y offsets and viewBox attributes. michael@0: */ michael@0: static gfxMatrix GetUserToCanvasTM(nsIFrame* aFrame, uint32_t aFor); michael@0: michael@0: /** michael@0: * Notify the descendants of aFrame of a change to one of their ancestors michael@0: * that might affect them. michael@0: */ michael@0: static void michael@0: NotifyChildrenOfSVGChange(nsIFrame *aFrame, uint32_t aFlags); michael@0: michael@0: /* michael@0: * Get frame's covered region by walking the children and doing union. michael@0: */ michael@0: static nsRect michael@0: GetCoveredRegion(const nsFrameList &aFrames); michael@0: michael@0: // Converts aPoint from an app unit point in outer- content rect space michael@0: // to an app unit point in a frame's SVG userspace. michael@0: // This is a temporary helper we should no longer need after bug 614732 is michael@0: // fixed. michael@0: static nsPoint michael@0: TransformOuterSVGPointToChildFrame(nsPoint aPoint, michael@0: const gfxMatrix& aFrameToCanvasTM, michael@0: nsPresContext* aPresContext); michael@0: michael@0: static nsRect michael@0: TransformFrameRectToOuterSVG(const nsRect& aRect, michael@0: const gfxMatrix& aMatrix, michael@0: nsPresContext* aPresContext); michael@0: michael@0: /* michael@0: * Convert a surface size to an integer for use by thebes michael@0: * possibly making it smaller in the process so the surface does not michael@0: * use excessive memory. michael@0: * michael@0: * @param aSize the desired surface size michael@0: * @param aResultOverflows true if the desired surface size is too big michael@0: * @return the surface size to use michael@0: */ michael@0: static gfxIntSize ConvertToSurfaceSize(const gfxSize& aSize, michael@0: bool *aResultOverflows); michael@0: michael@0: /* michael@0: * Hit test a given rectangle/matrix. michael@0: */ michael@0: static bool michael@0: HitTestRect(const mozilla::gfx::Matrix &aMatrix, michael@0: float aRX, float aRY, float aRWidth, float aRHeight, michael@0: float aX, float aY); michael@0: michael@0: michael@0: /** michael@0: * Get the clip rect for the given frame, taking into account the CSS 'clip' michael@0: * property. See: michael@0: * http://www.w3.org/TR/SVG11/masking.html#OverflowAndClipProperties michael@0: * The arguments for aX, aY, aWidth and aHeight should be the dimensions of michael@0: * the viewport established by aFrame. michael@0: */ michael@0: static gfxRect michael@0: GetClipRectForFrame(nsIFrame *aFrame, michael@0: float aX, float aY, float aWidth, float aHeight); michael@0: michael@0: static void SetClipRect(gfxContext *aContext, michael@0: const gfxMatrix &aCTM, michael@0: const gfxRect &aRect); michael@0: michael@0: /* Using group opacity instead of fill or stroke opacity on a michael@0: * geometry object seems to be a common authoring mistake. If we're michael@0: * not applying filters and not both stroking and filling, we can michael@0: * generate the same result without going through the overhead of a michael@0: * push/pop group. */ michael@0: static bool michael@0: CanOptimizeOpacity(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Take the CTM to userspace for an element, and adjust it to a CTM to its michael@0: * object bounding box space if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX. michael@0: * (I.e. so that [0,0] is at the top left of its bbox, and [1,1] is at the michael@0: * bottom right of its bbox). michael@0: * michael@0: * If the bbox is empty, this will return a singular matrix. michael@0: */ michael@0: static gfxMatrix michael@0: AdjustMatrixForUnits(const gfxMatrix &aMatrix, michael@0: nsSVGEnum *aUnits, michael@0: nsIFrame *aFrame); michael@0: michael@0: enum BBoxFlags { michael@0: eBBoxIncludeFill = 1 << 0, michael@0: eBBoxIncludeFillGeometry = 1 << 1, michael@0: eBBoxIncludeStroke = 1 << 2, michael@0: eBBoxIncludeStrokeGeometry = 1 << 3, michael@0: eBBoxIncludeMarkers = 1 << 4 michael@0: }; michael@0: /** michael@0: * Get the SVG bbox (the SVG spec's simplified idea of bounds) of aFrame in michael@0: * aFrame's userspace. michael@0: */ michael@0: static gfxRect GetBBox(nsIFrame *aFrame, michael@0: uint32_t aFlags = eBBoxIncludeFillGeometry); michael@0: michael@0: /* michael@0: * "User space" is the space that the frame's BBox (as calculated by michael@0: * nsSVGUtils::GetBBox) is in. "Frame space" is the space that has its origin michael@0: * at the top left of the union of the frame's border-box rects over all michael@0: * continuations. michael@0: * This function returns the offset one needs to add to something in frame michael@0: * space in order to get its coordinates in user space. michael@0: */ michael@0: static gfxPoint FrameSpaceInCSSPxToUserSpaceOffset(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Convert a userSpaceOnUse/objectBoundingBoxUnits rectangle that's specified michael@0: * using four nsSVGLength2 values into a user unit rectangle in user space. michael@0: * michael@0: * @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing michael@0: * the x, y, width and height values in that order michael@0: * @param aBBox the bounding box of the object the rect is relative to; michael@0: * may be null if aUnits is not SVG_UNIT_TYPE_OBJECTBOUNDINGBOX michael@0: * @param aFrame the object in which to interpret user-space units; michael@0: * may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX michael@0: */ michael@0: static gfxRect michael@0: GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, michael@0: const gfxRect &aBBox, nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Find the first frame, starting with aStartFrame and going up its michael@0: * parent chain, that is not an svgAFrame. michael@0: */ michael@0: static nsIFrame* GetFirstNonAAncestorFrame(nsIFrame* aStartFrame); michael@0: michael@0: static bool OuterSVGIsCallingReflowSVG(nsIFrame *aFrame); michael@0: static bool AnyOuterSVGIsCallingReflowSVG(nsIFrame *aFrame); michael@0: michael@0: /* michael@0: * Get any additional transforms that apply only to stroking michael@0: * e.g. non-scaling-stroke michael@0: */ michael@0: static gfxMatrix GetStrokeTransform(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Compute the maximum possible device space stroke extents of a path given michael@0: * the path's device space path extents, its stroke style and its ctm. michael@0: * michael@0: * This is a workaround for the lack of suitable cairo API for getting the michael@0: * tight device space stroke extents of a path. This basically gives us the michael@0: * tightest extents that we can guarantee fully enclose the inked stroke michael@0: * without doing the calculations for the actual tight extents. We exploit michael@0: * the fact that cairo does have an API for getting the tight device space michael@0: * fill/path extents. michael@0: * michael@0: * This should die once bug 478152 is fixed. michael@0: */ michael@0: static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents, michael@0: nsTextFrame* aFrame, michael@0: const gfxMatrix& aMatrix); michael@0: static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents, michael@0: nsSVGPathGeometryFrame* aFrame, michael@0: const gfxMatrix& aMatrix); michael@0: michael@0: /** michael@0: * Convert a floating-point value to a 32-bit integer value, clamping to michael@0: * the range of valid integers. michael@0: */ michael@0: static int32_t ClampToInt(double aVal) michael@0: { michael@0: return NS_lround(std::max(double(INT32_MIN), michael@0: std::min(double(INT32_MAX), aVal))); michael@0: } michael@0: michael@0: static nscolor GetFallbackOrPaintColor(gfxContext *aContext, michael@0: nsStyleContext *aStyleContext, michael@0: nsStyleSVGPaint nsStyleSVG::*aFillOrStroke); michael@0: michael@0: /** michael@0: * Set up cairo context with an object pattern michael@0: */ michael@0: static bool SetupContextPaint(gfxContext *aContext, michael@0: gfxTextContextPaint *aContextPaint, michael@0: const nsStyleSVGPaint& aPaint, michael@0: float aOpacity); michael@0: michael@0: /** michael@0: * Sets the current paint on the specified gfxContent to be the SVG 'fill' michael@0: * for the given frame. michael@0: */ michael@0: static bool SetupCairoFillPaint(nsIFrame* aFrame, gfxContext* aContext, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: /** michael@0: * Sets the current paint on the specified gfxContent to be the SVG 'stroke' michael@0: * for the given frame. michael@0: */ michael@0: static bool SetupCairoStrokePaint(nsIFrame* aFrame, gfxContext* aContext, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: static float GetOpacity(nsStyleSVGOpacitySource aOpacityType, michael@0: const float& aOpacity, michael@0: gfxTextContextPaint *aOuterContextPaint); michael@0: michael@0: /* michael@0: * @return false if there is no stroke michael@0: */ michael@0: static bool HasStroke(nsIFrame* aFrame, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: static float GetStrokeWidth(nsIFrame* aFrame, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: /* michael@0: * Set up a cairo context for measuring the bounding box of a stroked path. michael@0: */ michael@0: static void SetupCairoStrokeBBoxGeometry(nsIFrame* aFrame, michael@0: gfxContext *aContext, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: /* michael@0: * Set up a cairo context for a stroked path (including any dashing that michael@0: * applies). michael@0: */ michael@0: static void SetupCairoStrokeGeometry(nsIFrame* aFrame, gfxContext *aContext, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: /* michael@0: * Set up a cairo context for stroking, including setting up any stroke-related michael@0: * properties such as dashing and setting the current paint on the gfxContext. michael@0: */ michael@0: static bool SetupCairoStroke(nsIFrame* aFrame, gfxContext *aContext, michael@0: gfxTextContextPaint *aContextPaint = nullptr); michael@0: michael@0: /** michael@0: * This function returns a set of bit flags indicating which parts of the michael@0: * element (fill, stroke, bounds) should intercept pointer events. It takes michael@0: * into account the type of element and the value of the 'pointer-events' michael@0: * property on the element. michael@0: */ michael@0: static uint16_t GetGeometryHitTestFlags(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Render a SVG glyph. michael@0: * @param aElement the SVG glyph element to render michael@0: * @param aContext the thebes aContext to draw to michael@0: * @param aDrawMode fill or stroke or both (see DrawMode) michael@0: * @return true if rendering succeeded michael@0: */ michael@0: static bool PaintSVGGlyph(Element* aElement, gfxContext* aContext, michael@0: DrawMode aDrawMode, michael@0: gfxTextContextPaint* aContextPaint); michael@0: /** michael@0: * Get the extents of a SVG glyph. michael@0: * @param aElement the SVG glyph element michael@0: * @param aSVGToAppSpace the matrix mapping the SVG glyph space to the michael@0: * target context space michael@0: * @param aResult the result (valid when true is returned) michael@0: * @return true if calculating the extents succeeded michael@0: */ michael@0: static bool GetSVGGlyphExtents(Element* aElement, michael@0: const gfxMatrix& aSVGToAppSpace, michael@0: gfxRect* aResult); michael@0: michael@0: /** michael@0: * Returns the app unit canvas bounds of a userspace rect. michael@0: * michael@0: * @param aToCanvas Transform from userspace to canvas device space. michael@0: */ michael@0: static nsRect michael@0: ToCanvasBounds(const gfxRect &aUserspaceRect, michael@0: const gfxMatrix &aToCanvas, michael@0: const nsPresContext *presContext); michael@0: }; michael@0: michael@0: #endif