forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			599 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			599 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef LAYOUT_SVG_SVGUTILS_H_
 | |
| #define LAYOUT_SVG_SVGUTILS_H_
 | |
| 
 | |
| // include math.h to pick up definition of M_ maths defines e.g. M_PI
 | |
| #include <math.h>
 | |
| 
 | |
| #include "DrawMode.h"
 | |
| #include "ImgDrawResult.h"
 | |
| #include "gfx2DGlue.h"
 | |
| #include "gfxMatrix.h"
 | |
| #include "gfxPoint.h"
 | |
| #include "gfxRect.h"
 | |
| #include "mozilla/gfx/Rect.h"
 | |
| #include "nsAlgorithm.h"
 | |
| #include "nsChangeHint.h"
 | |
| #include "nsColor.h"
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsID.h"
 | |
| #include "nsIFrame.h"
 | |
| #include "nsISupportsBase.h"
 | |
| #include "nsMathUtils.h"
 | |
| #include "nsStyleStruct.h"
 | |
| #include <algorithm>
 | |
| 
 | |
| class gfxContext;
 | |
| class nsFrameList;
 | |
| class nsIContent;
 | |
| 
 | |
| class nsPresContext;
 | |
| class nsTextFrame;
 | |
| 
 | |
| struct nsStyleSVG;
 | |
| struct nsRect;
 | |
| 
 | |
| namespace mozilla {
 | |
| class SVGAnimatedEnumeration;
 | |
| class SVGAnimatedLength;
 | |
| class SVGContextPaint;
 | |
| struct SVGContextPaintImpl;
 | |
| class SVGDisplayContainerFrame;
 | |
| class SVGGeometryFrame;
 | |
| class SVGOuterSVGFrame;
 | |
| namespace dom {
 | |
| class Element;
 | |
| class SVGElement;
 | |
| class UserSpaceMetrics;
 | |
| }  // namespace dom
 | |
| namespace gfx {
 | |
| class DrawTarget;
 | |
| class GeneralPattern;
 | |
| }  // namespace gfx
 | |
| }  // namespace mozilla
 | |
| 
 | |
| // maximum dimension of an offscreen surface - choose so that
 | |
| // the surface size doesn't overflow a 32-bit signed int using
 | |
| // 4 bytes per pixel; in line with Factory::CheckSurfaceSize
 | |
| // In fact Macs can't even manage that
 | |
| #define NS_SVG_OFFSCREEN_MAX_DIMENSION 4096
 | |
| 
 | |
| #define SVG_HIT_TEST_FILL 0x01
 | |
| #define SVG_HIT_TEST_STROKE 0x02
 | |
| #define SVG_HIT_TEST_CHECK_MRECT 0x04
 | |
| 
 | |
| bool NS_SVGDisplayListHitTestingEnabled();
 | |
| bool NS_SVGDisplayListPaintingEnabled();
 | |
| bool NS_SVGNewGetBBoxEnabled();
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| /**
 | |
|  * Sometimes we need to distinguish between an empty box and a box
 | |
|  * that contains an element that has no size e.g. a point at the origin.
 | |
|  */
 | |
| class SVGBBox final {
 | |
|   using Rect = gfx::Rect;
 | |
| 
 | |
|  public:
 | |
|   SVGBBox() : mIsEmpty(true) {}
 | |
| 
 | |
|   MOZ_IMPLICIT SVGBBox(const Rect& aRect) : mBBox(aRect), mIsEmpty(false) {}
 | |
| 
 | |
|   MOZ_IMPLICIT SVGBBox(const gfxRect& aRect)
 | |
|       : mBBox(ToRect(aRect)), mIsEmpty(false) {}
 | |
| 
 | |
|   operator const Rect&() { return mBBox; }
 | |
| 
 | |
|   gfxRect ToThebesRect() const { return ThebesRect(mBBox); }
 | |
| 
 | |
|   bool IsEmpty() const { return mIsEmpty; }
 | |
| 
 | |
|   bool IsFinite() const { return mBBox.IsFinite(); }
 | |
| 
 | |
|   void Scale(float aScale) { mBBox.Scale(aScale); }
 | |
|   void MoveBy(float x, float y) { mBBox.MoveBy(x, y); }
 | |
| 
 | |
|   void UnionEdges(const SVGBBox& aSVGBBox) {
 | |
|     if (aSVGBBox.mIsEmpty) {
 | |
|       return;
 | |
|     }
 | |
|     mBBox = mIsEmpty ? aSVGBBox.mBBox : mBBox.UnionEdges(aSVGBBox.mBBox);
 | |
|     mIsEmpty = false;
 | |
|   }
 | |
| 
 | |
|   void Intersect(const SVGBBox& aSVGBBox) {
 | |
|     if (!mIsEmpty && !aSVGBBox.mIsEmpty) {
 | |
|       mBBox = mBBox.Intersect(aSVGBBox.mBBox);
 | |
|       if (mBBox.IsEmpty()) {
 | |
|         mIsEmpty = true;
 | |
|         mBBox = Rect(0, 0, 0, 0);
 | |
|       }
 | |
|     } else {
 | |
|       mIsEmpty = true;
 | |
|       mBBox = Rect(0, 0, 0, 0);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   Rect mBBox;
 | |
|   bool mIsEmpty;
 | |
| };
 | |
| 
 | |
| // GRRR WINDOWS HATE HATE HATE
 | |
| #undef CLIP_MASK
 | |
| 
 | |
| class MOZ_RAII SVGAutoRenderState final {
 | |
|   using DrawTarget = gfx::DrawTarget;
 | |
| 
 | |
|  public:
 | |
|   explicit SVGAutoRenderState(DrawTarget* aDrawTarget);
 | |
|   ~SVGAutoRenderState();
 | |
| 
 | |
|   void SetPaintingToWindow(bool aPaintingToWindow);
 | |
| 
 | |
|   static bool IsPaintingToWindow(DrawTarget* aDrawTarget);
 | |
| 
 | |
|  private:
 | |
|   DrawTarget* mDrawTarget;
 | |
|   void* mOriginalRenderState;
 | |
|   bool mPaintingToWindow;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * General functions used by all of SVG layout and possibly content code.
 | |
|  * If a method is used by content and depends only on other content methods
 | |
|  * it should go in SVGContentUtils instead.
 | |
|  */
 | |
| class SVGUtils final {
 | |
|  public:
 | |
|   using Element = dom::Element;
 | |
|   using SVGElement = dom::SVGElement;
 | |
|   using AntialiasMode = gfx::AntialiasMode;
 | |
|   using DrawTarget = gfx::DrawTarget;
 | |
|   using FillRule = gfx::FillRule;
 | |
|   using GeneralPattern = gfx::GeneralPattern;
 | |
|   using Size = gfx::Size;
 | |
|   using imgDrawingParams = image::imgDrawingParams;
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ObjectBoundingBoxProperty, gfxRect)
 | |
| 
 | |
|   /**
 | |
|    * Returns the frame's post-filter ink overflow rect when passed the
 | |
|    * frame's pre-filter ink overflow rect. If the frame is not currently
 | |
|    * being filtered, this function simply returns aUnfilteredRect.
 | |
|    */
 | |
|   static nsRect GetPostFilterInkOverflowRect(nsIFrame* aFrame,
 | |
|                                              const nsRect& aPreFilterRect);
 | |
| 
 | |
|   /**
 | |
|    * Schedules an update of the frame's bounds (which will in turn invalidate
 | |
|    * the new area that the frame should paint to).
 | |
|    *
 | |
|    * This does nothing when passed an NS_FRAME_IS_NONDISPLAY frame.
 | |
|    * In future we may want to allow ReflowSVG to be called on such frames,
 | |
|    * but that would be better implemented as a ForceReflowSVG function to
 | |
|    * be called synchronously while painting them without marking or paying
 | |
|    * attention to dirty bits like this function.
 | |
|    *
 | |
|    * This is very similar to PresShell::FrameNeedsReflow. The main reason that
 | |
|    * we have this function instead of using FrameNeedsReflow is because we need
 | |
|    * to be able to call it under SVGOuterSVGFrame::NotifyViewportChange when
 | |
|    * that function is called by SVGOuterSVGFrame::Reflow. FrameNeedsReflow
 | |
|    * is not suitable for calling during reflow though, and it asserts as much.
 | |
|    * The reason that we want to be callable under NotifyViewportChange is
 | |
|    * because we want to synchronously notify and dirty the SVGOuterSVGFrame's
 | |
|    * children so that when SVGOuterSVGFrame::DidReflow is called its children
 | |
|    * will be updated for the new size as appropriate. Otherwise we'd have to
 | |
|    * post an event to the event loop to mark dirty flags and request an update.
 | |
|    *
 | |
|    * Another reason that we don't currently want to call
 | |
|    * PresShell::FrameNeedsReflow is because passing eRestyle to it to get it to
 | |
|    * mark descendants dirty would cause it to descend through
 | |
|    * SVGForeignObjectFrame frames to mark their children dirty, but we want to
 | |
|    * handle SVGForeignObjectFrame specially. It would also do unnecessary work
 | |
|    * descending into NS_FRAME_IS_NONDISPLAY frames.
 | |
|    */
 | |
|   static void ScheduleReflowSVG(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the frame or any of its children need ReflowSVG
 | |
|    * to be called on them.
 | |
|    */
 | |
|   static bool NeedsReflowSVG(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Percentage lengths in SVG are resolved against the width/height of the
 | |
|    * nearest viewport (or its viewBox, if set). This helper returns the size
 | |
|    * of this "context" for the given frame so that percentage values can be
 | |
|    * resolved.
 | |
|    */
 | |
|   static Size GetContextSize(const nsIFrame* aFrame);
 | |
| 
 | |
|   /* Computes the input length in terms of object space coordinates.
 | |
|      Input: rect - bounding box
 | |
|             length - length to be converted
 | |
|   */
 | |
|   static float ObjectSpace(const gfxRect& aRect,
 | |
|                            const SVGAnimatedLength* aLength);
 | |
| 
 | |
|   /* Computes the input length in terms of user space coordinates.
 | |
|      Input: content - object to be used for determining user space
 | |
|      Input: length - length to be converted
 | |
|   */
 | |
|   static float UserSpace(SVGElement* aSVGElement,
 | |
|                          const SVGAnimatedLength* aLength);
 | |
|   static float UserSpace(nsIFrame* aNonSVGContext,
 | |
|                          const SVGAnimatedLength* aLength);
 | |
|   static float UserSpace(const dom::UserSpaceMetrics& aMetrics,
 | |
|                          const SVGAnimatedLength* aLength);
 | |
| 
 | |
|   /* Find the outermost SVG frame of the passed frame */
 | |
|   static SVGOuterSVGFrame* GetOuterSVGFrame(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Get the covered region for a frame. Return null if it's not an SVG frame.
 | |
|    * @param aRect gets a rectangle in app units
 | |
|    * @return the outer SVG frame which aRect is relative to
 | |
|    */
 | |
|   static nsIFrame* GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame,
 | |
|                                                     nsRect* aRect);
 | |
| 
 | |
|   /* Paint SVG frame with SVG effects - aDirtyRect is the area being
 | |
|    * redrawn, in device pixel coordinates relative to the outer svg */
 | |
|   static void PaintFrameWithEffects(nsIFrame* aFrame, gfxContext& aContext,
 | |
|                                     const gfxMatrix& aTransform,
 | |
|                                     imgDrawingParams& aImgParams,
 | |
|                                     const nsIntRect* aDirtyRect = nullptr);
 | |
| 
 | |
|   /* Hit testing - check if point hits the clipPath of indicated
 | |
|    * frame.  Returns true if no clipPath set. */
 | |
|   static bool HitTestClip(nsIFrame* aFrame, const gfxPoint& aPoint);
 | |
| 
 | |
|   /**
 | |
|    * Hit testing - check if point hits any children of aFrame.  aPoint is
 | |
|    * expected to be in the coordinate space established by aFrame for its
 | |
|    * children (e.g. the space established by the 'viewBox' attribute on <svg>).
 | |
|    */
 | |
|   static nsIFrame* HitTestChildren(SVGDisplayContainerFrame* aFrame,
 | |
|                                    const gfxPoint& aPoint);
 | |
| 
 | |
|   /*
 | |
|    * Returns the CanvasTM of the indicated frame, whether it's a
 | |
|    * child SVG frame, container SVG frame, or a regular frame.
 | |
|    * For regular frames, we just return an identity matrix.
 | |
|    */
 | |
|   static gfxMatrix GetCanvasTM(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Notify the descendants of aFrame of a change to one of their ancestors
 | |
|    * that might affect them.
 | |
|    */
 | |
|   static void NotifyChildrenOfSVGChange(nsIFrame* aFrame, uint32_t aFlags);
 | |
| 
 | |
|   static nsRect TransformFrameRectToOuterSVG(const nsRect& aRect,
 | |
|                                              const gfxMatrix& aMatrix,
 | |
|                                              nsPresContext* aPresContext);
 | |
| 
 | |
|   /*
 | |
|    * Convert a surface size to an integer for use by thebes
 | |
|    * possibly making it smaller in the process so the surface does not
 | |
|    * use excessive memory.
 | |
|    *
 | |
|    * @param aSize the desired surface size
 | |
|    * @param aResultOverflows true if the desired surface size is too big
 | |
|    * @return the surface size to use
 | |
|    */
 | |
|   static gfx::IntSize ConvertToSurfaceSize(const gfxSize& aSize,
 | |
|                                            bool* aResultOverflows);
 | |
| 
 | |
|   /*
 | |
|    * Hit test a given rectangle/matrix.
 | |
|    */
 | |
|   static bool HitTestRect(const gfx::Matrix& aMatrix, float aRX, float aRY,
 | |
|                           float aRWidth, float aRHeight, float aX, float aY);
 | |
| 
 | |
|   /**
 | |
|    * Get the clip rect for the given frame, taking into account the CSS 'clip'
 | |
|    * property. See:
 | |
|    * http://www.w3.org/TR/SVG11/masking.html#OverflowAndClipProperties
 | |
|    * The arguments for aX, aY, aWidth and aHeight should be the dimensions of
 | |
|    * the viewport established by aFrame.
 | |
|    */
 | |
|   static gfxRect GetClipRectForFrame(nsIFrame* aFrame, float aX, float aY,
 | |
|                                      float aWidth, float aHeight);
 | |
| 
 | |
|   static void SetClipRect(gfxContext* aContext, const gfxMatrix& aCTM,
 | |
|                           const gfxRect& aRect);
 | |
| 
 | |
|   /* Using group opacity instead of fill or stroke opacity on a
 | |
|    * geometry object seems to be a common authoring mistake.  If we're
 | |
|    * not applying filters and not both stroking and filling, we can
 | |
|    * generate the same result without going through the overhead of a
 | |
|    * push/pop group. */
 | |
|   static bool CanOptimizeOpacity(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Take the CTM to userspace for an element, and adjust it to a CTM to its
 | |
|    * object bounding box space if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX.
 | |
|    * (I.e. so that [0,0] is at the top left of its bbox, and [1,1] is at the
 | |
|    * bottom right of its bbox).
 | |
|    *
 | |
|    * If the bbox is empty, this will return a singular matrix.
 | |
|    *
 | |
|    * @param aFlags One or more of the BBoxFlags values defined below.
 | |
|    */
 | |
|   static gfxMatrix AdjustMatrixForUnits(const gfxMatrix& aMatrix,
 | |
|                                         SVGAnimatedEnumeration* aUnits,
 | |
|                                         nsIFrame* aFrame, uint32_t aFlags);
 | |
| 
 | |
|   enum BBoxFlags {
 | |
|     eBBoxIncludeFill = 1 << 0,
 | |
|     // Include the geometry of the fill even when the fill does not
 | |
|     // actually render (e.g. when fill="none" or fill-opacity="0")
 | |
|     eBBoxIncludeFillGeometry = 1 << 1,
 | |
|     eBBoxIncludeStroke = 1 << 2,
 | |
|     // Include the geometry of the stroke even when the stroke does not
 | |
|     // actually render (e.g. when stroke="none" or stroke-opacity="0")
 | |
|     eBBoxIncludeStrokeGeometry = 1 << 3,
 | |
|     eBBoxIncludeMarkers = 1 << 4,
 | |
|     eBBoxIncludeClipped = 1 << 5,
 | |
|     // Normally a getBBox call on outer-<svg> should only return the
 | |
|     // bounds of the elements children. This flag will cause the
 | |
|     // element's bounds to be returned instead.
 | |
|     eUseFrameBoundsForOuterSVG = 1 << 6,
 | |
|     // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
 | |
|     eForGetClientRects = 1 << 7,
 | |
|     // If the given frame is an HTML element, only include the region of the
 | |
|     // given frame, instead of all continuations of it, while computing bbox if
 | |
|     // this flag is set.
 | |
|     eIncludeOnlyCurrentFrameForNonSVGElement = 1 << 8,
 | |
|     // This flag is only has an effect when the target is a <use> element.
 | |
|     // getBBox returns the bounds of the elements children in user space if
 | |
|     // this flag is set; Otherwise, getBBox returns the union bounds in
 | |
|     // the coordinate system formed by the <use> element.
 | |
|     eUseUserSpaceOfUseElement = 1 << 9,
 | |
|     // For a frame with a clip-path, if this flag is set then the result
 | |
|     // will not be clipped to the bbox of the content inside the clip-path.
 | |
|     eDoNotClipToBBoxOfContentInsideClipPath = 1 << 10,
 | |
|   };
 | |
|   /**
 | |
|    * This function in primarily for implementing the SVG DOM function getBBox()
 | |
|    * and the SVG attribute value 'objectBoundingBox'.  However, it has been
 | |
|    * extended with various extra parameters in order to become more of a
 | |
|    * general purpose getter of all sorts of bounds that we might need to obtain
 | |
|    * for SVG elements, or even for other elements that have SVG effects applied
 | |
|    * to them.
 | |
|    *
 | |
|    * @param aFrame The frame of the element for which the bounds are to be
 | |
|    *   obtained.
 | |
|    * @param aFlags One or more of the BBoxFlags values defined above.
 | |
|    * @param aToBoundsSpace If not specified the returned rect is in aFrame's
 | |
|    *   element's "user space". A matrix can optionally be pass to specify a
 | |
|    *   transform from aFrame's user space to the bounds space of interest
 | |
|    *   (typically this will be the ancestor SVGOuterSVGFrame, but it could be
 | |
|    *   to any other coordinate space).
 | |
|    */
 | |
|   static gfxRect GetBBox(nsIFrame* aFrame,
 | |
|                          // If the default arg changes, update the handling for
 | |
|                          // ObjectBoundingBoxProperty() in the implementation.
 | |
|                          uint32_t aFlags = eBBoxIncludeFillGeometry,
 | |
|                          const gfxMatrix* aToBoundsSpace = nullptr);
 | |
| 
 | |
|   /*
 | |
|    * "User space" is the space that the frame's BBox (as calculated by
 | |
|    * SVGUtils::GetBBox) is in. "Frame space" is the space that has its origin
 | |
|    * at the top left of the union of the frame's border-box rects over all
 | |
|    * continuations.
 | |
|    * This function returns the offset one needs to add to something in frame
 | |
|    * space in order to get its coordinates in user space.
 | |
|    */
 | |
|   static gfxPoint FrameSpaceInCSSPxToUserSpaceOffset(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Convert a userSpaceOnUse/objectBoundingBoxUnits rectangle that's specified
 | |
|    * using four SVGAnimatedLength values into a user unit rectangle in user
 | |
|    * space.
 | |
|    *
 | |
|    * @param aXYWH pointer to 4 consecutive SVGAnimatedLength objects containing
 | |
|    * the x, y, width and height values in that order
 | |
|    * @param aBBox the bounding box of the object the rect is relative to;
 | |
|    * may be null if aUnits is not SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
 | |
|    * @param aFrame the object in which to interpret user-space units;
 | |
|    * may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
 | |
|    */
 | |
|   static gfxRect GetRelativeRect(uint16_t aUnits,
 | |
|                                  const SVGAnimatedLength* aXYWH,
 | |
|                                  const gfxRect& aBBox, nsIFrame* aFrame);
 | |
| 
 | |
|   static gfxRect GetRelativeRect(uint16_t aUnits,
 | |
|                                  const SVGAnimatedLength* aXYWH,
 | |
|                                  const gfxRect& aBBox,
 | |
|                                  const dom::UserSpaceMetrics& aMetrics);
 | |
| 
 | |
|   /**
 | |
|    * Find the first frame, starting with aStartFrame and going up its
 | |
|    * parent chain, that is not an svgAFrame.
 | |
|    */
 | |
|   static nsIFrame* GetFirstNonAAncestorFrame(nsIFrame* aStartFrame);
 | |
| 
 | |
|   static bool OuterSVGIsCallingReflowSVG(nsIFrame* aFrame);
 | |
|   static bool AnyOuterSVGIsCallingReflowSVG(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * See https://svgwg.org/svg2-draft/painting.html#NonScalingStroke
 | |
|    *
 | |
|    * If the computed value of the 'vector-effect' property on aFrame is
 | |
|    * 'non-scaling-stroke', then this function will set aUserToOuterSVG to the
 | |
|    * transform from aFrame's SVG user space to the initial coordinate system
 | |
|    * established by the viewport of aFrame's outer-<svg>'s (the coordinate
 | |
|    * system in which the stroke is fixed).  If aUserToOuterSVG is set to a
 | |
|    * non-identity matrix this function returns true, else it returns false.
 | |
|    */
 | |
|   static bool GetNonScalingStrokeTransform(nsIFrame* aFrame,
 | |
|                                            gfxMatrix* aUserToOuterSVG);
 | |
| 
 | |
|   /**
 | |
|    * Compute the maximum possible device space stroke extents of a path given
 | |
|    * the path's device space path extents, its stroke style and its ctm.
 | |
|    *
 | |
|    * This is a workaround for the lack of suitable cairo API for getting the
 | |
|    * tight device space stroke extents of a path. This basically gives us the
 | |
|    * tightest extents that we can guarantee fully enclose the inked stroke
 | |
|    * without doing the calculations for the actual tight extents. We exploit
 | |
|    * the fact that cairo does have an API for getting the tight device space
 | |
|    * fill/path extents.
 | |
|    *
 | |
|    * This should die once bug 478152 is fixed.
 | |
|    */
 | |
|   static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
 | |
|                                                nsTextFrame* aFrame,
 | |
|                                                const gfxMatrix& aMatrix);
 | |
|   static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
 | |
|                                                SVGGeometryFrame* aFrame,
 | |
|                                                const gfxMatrix& aMatrix);
 | |
| 
 | |
|   /**
 | |
|    * Convert a floating-point value to a 32-bit integer value, clamping to
 | |
|    * the range of valid integers.
 | |
|    */
 | |
|   static int32_t ClampToInt(double aVal) {
 | |
|     return NS_lround(
 | |
|         std::max(double(INT32_MIN), std::min(double(INT32_MAX), aVal)));
 | |
|   }
 | |
| 
 | |
|   static nscolor GetFallbackOrPaintColor(
 | |
|       const ComputedStyle&, StyleSVGPaint nsStyleSVG::*aFillOrStroke);
 | |
| 
 | |
|   static void MakeFillPatternFor(nsIFrame* aFrame, gfxContext* aContext,
 | |
|                                  GeneralPattern* aOutPattern,
 | |
|                                  imgDrawingParams& aImgParams,
 | |
|                                  SVGContextPaint* aContextPaint = nullptr);
 | |
| 
 | |
|   static void MakeStrokePatternFor(nsIFrame* aFrame, gfxContext* aContext,
 | |
|                                    GeneralPattern* aOutPattern,
 | |
|                                    imgDrawingParams& aImgParams,
 | |
|                                    SVGContextPaint* aContextPaint = nullptr);
 | |
| 
 | |
|   static float GetOpacity(const StyleSVGOpacity&, SVGContextPaint*);
 | |
| 
 | |
|   /*
 | |
|    * @return false if there is no stroke
 | |
|    */
 | |
|   static bool HasStroke(nsIFrame* aFrame,
 | |
|                         SVGContextPaint* aContextPaint = nullptr);
 | |
| 
 | |
|   static float GetStrokeWidth(nsIFrame* aFrame,
 | |
|                               SVGContextPaint* aContextPaint = nullptr);
 | |
| 
 | |
|   /*
 | |
|    * Set up a context for a stroked path (including any dashing that applies).
 | |
|    */
 | |
|   static void SetupStrokeGeometry(nsIFrame* aFrame, gfxContext* aContext,
 | |
|                                   SVGContextPaint* aContextPaint = nullptr);
 | |
| 
 | |
|   /**
 | |
|    * This function returns a set of bit flags indicating which parts of the
 | |
|    * element (fill, stroke, bounds) should intercept pointer events. It takes
 | |
|    * into account the type of element and the value of the 'pointer-events'
 | |
|    * property on the element.
 | |
|    */
 | |
|   static uint16_t GetGeometryHitTestFlags(nsIFrame* aFrame);
 | |
| 
 | |
|   static FillRule ToFillRule(StyleFillRule aFillRule) {
 | |
|     return aFillRule == StyleFillRule::Evenodd ? FillRule::FILL_EVEN_ODD
 | |
|                                                : FillRule::FILL_WINDING;
 | |
|   }
 | |
| 
 | |
|   static AntialiasMode ToAntialiasMode(StyleTextRendering aTextRendering) {
 | |
|     return aTextRendering == StyleTextRendering::Optimizespeed
 | |
|                ? AntialiasMode::NONE
 | |
|                : AntialiasMode::SUBPIXEL;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Render a SVG glyph.
 | |
|    * @param aElement the SVG glyph element to render
 | |
|    * @param aContext the thebes aContext to draw to
 | |
|    * @return true if rendering succeeded
 | |
|    */
 | |
|   static void PaintSVGGlyph(Element* aElement, gfxContext* aContext);
 | |
| 
 | |
|   /**
 | |
|    * Get the extents of a SVG glyph.
 | |
|    * @param aElement the SVG glyph element
 | |
|    * @param aSVGToAppSpace the matrix mapping the SVG glyph space to the
 | |
|    *   target context space
 | |
|    * @param aResult the result (valid when true is returned)
 | |
|    * @return true if calculating the extents succeeded
 | |
|    */
 | |
|   static bool GetSVGGlyphExtents(Element* aElement,
 | |
|                                  const gfxMatrix& aSVGToAppSpace,
 | |
|                                  gfxRect* aResult);
 | |
| 
 | |
|   /**
 | |
|    * Returns the app unit canvas bounds of a userspace rect.
 | |
|    *
 | |
|    * @param aToCanvas Transform from userspace to canvas device space.
 | |
|    */
 | |
|   static nsRect ToCanvasBounds(const gfxRect& aUserspaceRect,
 | |
|                                const gfxMatrix& aToCanvas,
 | |
|                                const nsPresContext* presContext);
 | |
| 
 | |
|   struct MaskUsage {
 | |
|     bool shouldGenerateMaskLayer;
 | |
|     bool shouldGenerateClipMaskLayer;
 | |
|     bool shouldApplyClipPath;
 | |
|     bool shouldApplyBasicShapeOrPath;
 | |
|     float opacity;
 | |
| 
 | |
|     MaskUsage()
 | |
|         : shouldGenerateMaskLayer(false),
 | |
|           shouldGenerateClipMaskLayer(false),
 | |
|           shouldApplyClipPath(false),
 | |
|           shouldApplyBasicShapeOrPath(false),
 | |
|           opacity(0.0) {}
 | |
| 
 | |
|     bool shouldDoSomething() {
 | |
|       return shouldGenerateMaskLayer || shouldGenerateClipMaskLayer ||
 | |
|              shouldApplyClipPath || shouldApplyBasicShapeOrPath ||
 | |
|              opacity != 1.0;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   static void DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
 | |
|                                  MaskUsage& aUsage);
 | |
| 
 | |
|   static float ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity);
 | |
| 
 | |
|   /**
 | |
|    * SVG frames expect to paint in SVG user units, which are equal to CSS px
 | |
|    * units. This method provides a transform matrix to multiply onto a
 | |
|    * gfxContext's current transform to convert the context's current units from
 | |
|    * its usual dev pixels to SVG user units/CSS px to keep the SVG code happy.
 | |
|    */
 | |
|   static gfxMatrix GetCSSPxToDevPxMatrix(nsIFrame* aNonSVGFrame);
 | |
| 
 | |
|   static bool IsInSVGTextSubtree(const nsIFrame* aFrame) {
 | |
|     // Returns true if the frame is an SVGTextFrame or one of its descendants.
 | |
|     return aFrame->HasAnyStateBits(NS_FRAME_IS_SVG_TEXT);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * It is a replacement of
 | |
|    * SVGElement::PrependLocalTransformsTo(eUserSpaceToParent).
 | |
|    * If no CSS transform is involved, they should behave exactly the same;
 | |
|    * if there are CSS transforms, this one will take them into account
 | |
|    * while SVGElement::PrependLocalTransformsTo won't.
 | |
|    */
 | |
|   static gfxMatrix GetTransformMatrixInUserSpace(const nsIFrame* aFrame);
 | |
| };
 | |
| 
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // LAYOUT_SVG_SVGUTILS_H_
 | 
