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