Blame layout/svg/nsSVGUtils.h

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