|
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 MOZILLA_SVGCONTEXTPAINT_H_
|
|
Packit |
f0b94e |
#define MOZILLA_SVGCONTEXTPAINT_H_
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "DrawMode.h"
|
|
Packit |
f0b94e |
#include "gfxMatrix.h"
|
|
Packit |
f0b94e |
#include "gfxPattern.h"
|
|
Packit |
f0b94e |
#include "gfxTypes.h"
|
|
Packit |
f0b94e |
#include "gfxUtils.h"
|
|
Packit |
f0b94e |
#include "mozilla/AlreadyAddRefed.h"
|
|
Packit |
f0b94e |
#include "mozilla/Assertions.h"
|
|
Packit |
f0b94e |
#include "mozilla/gfx/2D.h"
|
|
Packit |
f0b94e |
#include "nsColor.h"
|
|
Packit |
f0b94e |
#include "nsStyleStruct.h"
|
|
Packit |
f0b94e |
#include "nsTArray.h"
|
|
Packit |
f0b94e |
#include "ImgDrawResult.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class gfxContext;
|
|
Packit |
f0b94e |
class nsIDocument;
|
|
Packit |
f0b94e |
class nsSVGPaintServerFrame;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace mozilla {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* This class is used to pass information about a context element through to
|
|
Packit |
f0b94e |
* SVG painting code in order to resolve the 'context-fill' and related
|
|
Packit |
f0b94e |
* keywords. See:
|
|
Packit |
f0b94e |
*
|
|
Packit |
f0b94e |
* https://www.w3.org/TR/SVG2/painting.html#context-paint
|
|
Packit |
f0b94e |
*
|
|
Packit |
f0b94e |
* This feature allows the color in an SVG-in-OpenType glyph to come from the
|
|
Packit |
f0b94e |
* computed style for the text that is being drawn, for example, or for color
|
|
Packit |
f0b94e |
* in an SVG embedded by an element to come from the embedding ![]()
|
|
Packit |
f0b94e |
* element.
|
|
Packit |
f0b94e |
*
|
|
Packit |
f0b94e |
* This class is reference counted so that it can be shared among many similar
|
|
Packit |
f0b94e |
* SVGImageContext objects. (SVGImageContext objects are frequently
|
|
Packit |
f0b94e |
* copy-constructed with small modifications, and we'd like for those copies to
|
|
Packit |
f0b94e |
* be able to share their context-paint data cheaply.) However, in most cases,
|
|
Packit |
f0b94e |
* SVGContextPaint instances are stored in a local RefPtr and only last for the
|
|
Packit |
f0b94e |
* duration of a function call.
|
|
Packit |
f0b94e |
* XXX Note: SVGImageContext doesn't actually have a SVGContextPaint member yet,
|
|
Packit |
f0b94e |
* but it will in a later patch in the patch series that added this comment.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
class SVGContextPaint : public RefCounted<SVGContextPaint> {
|
|
Packit |
f0b94e |
protected:
|
|
Packit |
f0b94e |
typedef mozilla::gfx::DrawTarget DrawTarget;
|
|
Packit |
f0b94e |
typedef mozilla::gfx::Float Float;
|
|
Packit |
f0b94e |
typedef mozilla::image::imgDrawingParams imgDrawingParams;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
SVGContextPaint() : mDashOffset(0.0f), mStrokeWidth(0.0f) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
MOZ_DECLARE_REFCOUNTED_TYPENAME(SVGContextPaint)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
virtual ~SVGContextPaint() {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
virtual already_AddRefed<gfxPattern> GetFillPattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) = 0;
|
|
Packit |
f0b94e |
virtual already_AddRefed<gfxPattern> GetStrokePattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) = 0;
|
|
Packit |
f0b94e |
virtual float GetFillOpacity() const = 0;
|
|
Packit |
f0b94e |
virtual float GetStrokeOpacity() const = 0;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
|
|
Packit |
f0b94e |
const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) {
|
|
Packit |
f0b94e |
return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM, aImgParams);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
|
|
Packit |
f0b94e |
const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) {
|
|
Packit |
f0b94e |
return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM, aImgParams);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
static SVGContextPaint* GetContextPaint(nsIContent* aContent);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// XXX This gets the geometry params from the gfxContext. We should get that
|
|
Packit |
f0b94e |
// information from the actual paint context!
|
|
Packit |
f0b94e |
void InitStrokeGeometry(gfxContext* aContext, float devUnitsPerSVGUnit);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
const FallibleTArray<Float>& GetStrokeDashArray() const { return mDashes; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
Float GetStrokeDashOffset() const { return mDashOffset; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
Float GetStrokeWidth() const { return mStrokeWidth; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
virtual uint32_t Hash() const {
|
|
Packit |
f0b94e |
MOZ_ASSERT_UNREACHABLE(
|
|
Packit |
f0b94e |
"Only VectorImage needs to hash, and that should "
|
|
Packit |
f0b94e |
"only be operating on our SVGEmbeddingContextPaint "
|
|
Packit |
f0b94e |
"subclass");
|
|
Packit |
f0b94e |
return 0;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* Returns true if image context paint is allowed to be used in an image that
|
|
Packit |
f0b94e |
* has the given URI, else returns false.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
static bool IsAllowedForImageFromURI(nsIURI* aURI);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
// Member-vars are initialized in InitStrokeGeometry.
|
|
Packit |
f0b94e |
FallibleTArray<Float> mDashes;
|
|
Packit |
f0b94e |
MOZ_INIT_OUTSIDE_CTOR Float mDashOffset;
|
|
Packit |
f0b94e |
MOZ_INIT_OUTSIDE_CTOR Float mStrokeWidth;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* RAII class used to temporarily set and remove an SVGContextPaint while a
|
|
Packit |
f0b94e |
* piece of SVG is being painted. The context paint is set on the SVG's owner
|
|
Packit |
f0b94e |
* document, as expected by SVGContextPaint::GetContextPaint. Any pre-existing
|
|
Packit |
f0b94e |
* context paint is restored after this class removes the context paint that it
|
|
Packit |
f0b94e |
* set.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
class MOZ_RAII AutoSetRestoreSVGContextPaint {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
AutoSetRestoreSVGContextPaint(const SVGContextPaint* aContextPaint,
|
|
Packit |
f0b94e |
nsIDocument* aSVGDocument);
|
|
Packit |
f0b94e |
~AutoSetRestoreSVGContextPaint();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsIDocument* mSVGDocument;
|
|
Packit |
f0b94e |
// The context paint that needs to be restored by our dtor after it removes
|
|
Packit |
f0b94e |
// aContextPaint:
|
|
Packit |
f0b94e |
void* mOuterContextPaint;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* This class should be flattened into SVGContextPaint once we get rid of the
|
|
Packit |
f0b94e |
* other sub-class (SimpleTextContextPaint).
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
struct SVGContextPaintImpl : public SVGContextPaint {
|
|
Packit |
f0b94e |
protected:
|
|
Packit |
f0b94e |
typedef mozilla::gfx::DrawTarget DrawTarget;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
DrawMode Init(const DrawTarget* aDrawTarget, const gfxMatrix& aContextMatrix,
|
|
Packit |
f0b94e |
nsIFrame* aFrame, SVGContextPaint* aOuterContextPaint,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetFillPattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) override;
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetStrokePattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) override;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
|
|
Packit |
f0b94e |
float GetFillOpacity() const override { return mFillOpacity; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
|
|
Packit |
f0b94e |
float GetStrokeOpacity() const override { return mStrokeOpacity; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
struct Paint {
|
|
Packit |
f0b94e |
Paint() : mPaintType(eStyleSVGPaintType_None) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetPaintServer(nsIFrame* aFrame, const gfxMatrix& aContextMatrix,
|
|
Packit |
f0b94e |
nsSVGPaintServerFrame* aPaintServerFrame) {
|
|
Packit |
f0b94e |
mPaintType = eStyleSVGPaintType_Server;
|
|
Packit |
f0b94e |
mPaintDefinition.mPaintServerFrame = aPaintServerFrame;
|
|
Packit |
f0b94e |
mFrame = aFrame;
|
|
Packit |
f0b94e |
mContextMatrix = aContextMatrix;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetColor(const nscolor& aColor) {
|
|
Packit |
f0b94e |
mPaintType = eStyleSVGPaintType_Color;
|
|
Packit |
f0b94e |
mPaintDefinition.mColor = aColor;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetContextPaint(SVGContextPaint* aContextPaint,
|
|
Packit |
f0b94e |
nsStyleSVGPaintType aPaintType) {
|
|
Packit |
f0b94e |
NS_ASSERTION(aPaintType == eStyleSVGPaintType_ContextFill ||
|
|
Packit |
f0b94e |
aPaintType == eStyleSVGPaintType_ContextStroke,
|
|
Packit |
f0b94e |
"Invalid context paint type");
|
|
Packit |
f0b94e |
mPaintType = aPaintType;
|
|
Packit |
f0b94e |
mPaintDefinition.mContextPaint = aContextPaint;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
union {
|
|
Packit |
f0b94e |
nsSVGPaintServerFrame* mPaintServerFrame;
|
|
Packit |
f0b94e |
SVGContextPaint* mContextPaint;
|
|
Packit |
f0b94e |
nscolor mColor;
|
|
Packit |
f0b94e |
} mPaintDefinition;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Initialized (if needed) in SetPaintServer():
|
|
Packit |
f0b94e |
MOZ_INIT_OUTSIDE_CTOR nsIFrame* mFrame;
|
|
Packit |
f0b94e |
// CTM defining the user space for the pattern we will use.
|
|
Packit |
f0b94e |
gfxMatrix mContextMatrix;
|
|
Packit |
f0b94e |
nsStyleSVGPaintType mPaintType;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Device-space-to-pattern-space
|
|
Packit |
f0b94e |
gfxMatrix mPatternMatrix;
|
|
Packit |
f0b94e |
nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetPattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aOpacity,
|
|
Packit |
f0b94e |
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams);
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
Paint mFillPaint;
|
|
Packit |
f0b94e |
Paint mStrokePaint;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
float mFillOpacity;
|
|
Packit |
f0b94e |
float mStrokeOpacity;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* This class is used to pass context paint to an SVG image when an element
|
|
Packit |
f0b94e |
* references that image (e.g. via HTML or SVG <image>, or by referencing
|
|
Packit |
f0b94e |
* it from a CSS property such as 'background-image'). In this case we only
|
|
Packit |
f0b94e |
* support context colors and not paint servers.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
class SVGEmbeddingContextPaint : public SVGContextPaint {
|
|
Packit |
f0b94e |
typedef gfx::Color Color;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
SVGEmbeddingContextPaint() : mFillOpacity(1.0f), mStrokeOpacity(1.0f) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
bool operator==(const SVGEmbeddingContextPaint& aOther) const {
|
|
Packit |
f0b94e |
MOZ_ASSERT(GetStrokeWidth() == aOther.GetStrokeWidth() &&
|
|
Packit |
f0b94e |
GetStrokeDashOffset() == aOther.GetStrokeDashOffset() &&
|
|
Packit |
f0b94e |
GetStrokeDashArray() == aOther.GetStrokeDashArray(),
|
|
Packit |
f0b94e |
"We don't currently include these in the context information "
|
|
Packit |
f0b94e |
"from an embedding element");
|
|
Packit |
f0b94e |
return mFill == aOther.mFill && mStroke == aOther.mStroke &&
|
|
Packit |
f0b94e |
mFillOpacity == aOther.mFillOpacity &&
|
|
Packit |
f0b94e |
mStrokeOpacity == aOther.mStrokeOpacity;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetFill(nscolor aFill) { mFill.emplace(gfx::ToDeviceColor(aFill)); }
|
|
Packit |
f0b94e |
const Maybe<Color>& GetFill() const { return mFill; }
|
|
Packit |
f0b94e |
void SetStroke(nscolor aStroke) {
|
|
Packit |
f0b94e |
mStroke.emplace(gfx::ToDeviceColor(aStroke));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
const Maybe<Color>& GetStroke() const { return mStroke; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* Returns a pattern of type PatternType::COLOR, or else nullptr.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetFillPattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aFillOpacity, const gfxMatrix& aCTM,
|
|
Packit |
f0b94e |
imgDrawingParams& aImgParams) override;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/**
|
|
Packit |
f0b94e |
* Returns a pattern of type PatternType::COLOR, or else nullptr.
|
|
Packit |
f0b94e |
*/
|
|
Packit |
f0b94e |
already_AddRefed<gfxPattern> GetStrokePattern(
|
|
Packit |
f0b94e |
const DrawTarget* aDrawTarget, float aStrokeOpacity,
|
|
Packit |
f0b94e |
const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
|
|
Packit |
f0b94e |
float GetFillOpacity() const override { return mFillOpacity; };
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
|
|
Packit |
f0b94e |
float GetStrokeOpacity() const override { return mStrokeOpacity; };
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
uint32_t Hash() const override;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
Maybe<Color> mFill;
|
|
Packit |
f0b94e |
Maybe<Color> mStroke;
|
|
Packit |
f0b94e |
float mFillOpacity;
|
|
Packit |
f0b94e |
float mStrokeOpacity;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace mozilla
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#endif // MOZILLA_SVGCONTEXTPAINT_H_
|