|
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
|