1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef _MOZILLA_GFX_DRAWTARGET_CAIRO_H_
8 #define _MOZILLA_GFX_DRAWTARGET_CAIRO_H_
9 
10 #include "2D.h"
11 #include "cairo.h"
12 #include "PathCairo.h"
13 
14 #include <vector>
15 
16 namespace mozilla {
17 namespace gfx {
18 
19 class SourceSurfaceCairo;
20 
21 class GradientStopsCairo : public GradientStops {
22  public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsCairo,override)23   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsCairo, override)
24 
25   GradientStopsCairo(GradientStop *aStops, uint32_t aNumStops,
26                      ExtendMode aExtendMode)
27       : mExtendMode(aExtendMode) {
28     for (uint32_t i = 0; i < aNumStops; ++i) {
29       mStops.push_back(aStops[i]);
30     }
31   }
32 
~GradientStopsCairo()33   virtual ~GradientStopsCairo() {}
34 
GetStops()35   const std::vector<GradientStop> &GetStops() const { return mStops; }
36 
GetExtendMode()37   ExtendMode GetExtendMode() const { return mExtendMode; }
38 
GetBackendType()39   virtual BackendType GetBackendType() const override {
40     return BackendType::CAIRO;
41   }
42 
43  private:
44   std::vector<GradientStop> mStops;
45   ExtendMode mExtendMode;
46 };
47 
48 class DrawTargetCairo final : public DrawTarget {
49  public:
50   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo, override)
51   friend class BorrowedCairoContext;
52   friend class BorrowedXlibDrawable;
53 
54   DrawTargetCairo();
55   virtual ~DrawTargetCairo();
56 
57   virtual bool IsValid() const override;
58   virtual DrawTargetType GetType() const override;
GetBackendType()59   virtual BackendType GetBackendType() const override {
60     return BackendType::CAIRO;
61   }
62   virtual already_AddRefed<SourceSurface> Snapshot() override;
63   virtual IntSize GetSize() const override;
64 
65   virtual bool IsCurrentGroupOpaque() override;
66 
67   virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) override;
68 
69   virtual bool LockBits(uint8_t **aData, IntSize *aSize, int32_t *aStride,
70                         SurfaceFormat *aFormat,
71                         IntPoint *aOrigin = nullptr) override;
72   virtual void ReleaseBits(uint8_t *aData) override;
73 
74   virtual void Flush() override;
75   virtual void DrawSurface(
76       SourceSurface *aSurface, const Rect &aDest, const Rect &aSource,
77       const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
78       const DrawOptions &aOptions = DrawOptions()) override;
79   virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect,
80                           const Point &aDestPoint,
81                           const DrawOptions &aOptions = DrawOptions()) override;
82   virtual void DrawSurfaceWithShadow(SourceSurface *aSurface,
83                                      const Point &aDest, const Color &aColor,
84                                      const Point &aOffset, Float aSigma,
85                                      CompositionOp aOperator) override;
86 
87   virtual void ClearRect(const Rect &aRect) override;
88 
89   virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect,
90                            const IntPoint &aDestination) override;
91   virtual void CopyRect(const IntRect &aSourceRect,
92                         const IntPoint &aDestination) override;
93 
94   virtual void FillRect(const Rect &aRect, const Pattern &aPattern,
95                         const DrawOptions &aOptions = DrawOptions()) override;
96   virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern,
97                           const StrokeOptions &aStrokeOptions = StrokeOptions(),
98                           const DrawOptions &aOptions = DrawOptions()) override;
99   virtual void StrokeLine(const Point &aStart, const Point &aEnd,
100                           const Pattern &aPattern,
101                           const StrokeOptions &aStrokeOptions = StrokeOptions(),
102                           const DrawOptions &aOptions = DrawOptions()) override;
103 
104   virtual void Stroke(const Path *aPath, const Pattern &aPattern,
105                       const StrokeOptions &aStrokeOptions = StrokeOptions(),
106                       const DrawOptions &aOptions = DrawOptions()) override;
107 
108   virtual void Fill(const Path *aPath, const Pattern &aPattern,
109                     const DrawOptions &aOptions = DrawOptions()) override;
110 
111   virtual void FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer,
112                           const Pattern &aPattern,
113                           const DrawOptions &aOptions) override;
114   virtual void Mask(const Pattern &aSource, const Pattern &aMask,
115                     const DrawOptions &aOptions = DrawOptions()) override;
116   virtual void MaskSurface(
117       const Pattern &aSource, SourceSurface *aMask, Point aOffset,
118       const DrawOptions &aOptions = DrawOptions()) override;
119 
120   virtual bool Draw3DTransformedSurface(SourceSurface *aSurface,
121                                         const Matrix4x4 &aMatrix) override;
122 
123   virtual void PushClip(const Path *aPath) override;
124   virtual void PushClipRect(const Rect &aRect) override;
125   virtual void PopClip() override;
126   virtual void PushLayer(bool aOpaque, Float aOpacity, SourceSurface *aMask,
127                          const Matrix &aMaskTransform,
128                          const IntRect &aBounds = IntRect(),
129                          bool aCopyBackground = false) override;
130   virtual void PopLayer() override;
131 
132   virtual already_AddRefed<PathBuilder> CreatePathBuilder(
133       FillRule aFillRule = FillRule::FILL_WINDING) const override;
134 
135   virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
136       unsigned char *aData, const IntSize &aSize, int32_t aStride,
137       SurfaceFormat aFormat) const override;
138   virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(
139       SourceSurface *aSurface) const override;
140   virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
141       const NativeSurface &aSurface) const override;
142   virtual already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
143       const IntSize &aSize, SurfaceFormat aFormat) const override;
144   virtual already_AddRefed<DrawTarget> CreateShadowDrawTarget(
145       const IntSize &aSize, SurfaceFormat aFormat, float aSigma) const override;
146 
147   virtual already_AddRefed<GradientStops> CreateGradientStops(
148       GradientStop *aStops, uint32_t aNumStops,
149       ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
150 
151   virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
152 
153   virtual void GetGlyphRasterizationMetrics(
154       ScaledFont *aScaledFont, const uint16_t *aGlyphIndices,
155       uint32_t aNumGlyphs, GlyphMetrics *aGlyphMetrics) override;
156 
157   virtual void *GetNativeSurface(NativeSurfaceType aType) override;
158 
159   bool Init(cairo_surface_t *aSurface, const IntSize &aSize,
160             SurfaceFormat *aFormat = nullptr);
161   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
162   bool Init(unsigned char *aData, const IntSize &aSize, int32_t aStride,
163             SurfaceFormat aFormat);
164 
165   virtual void SetTransform(const Matrix &aTransform) override;
166 
DetachAllSnapshots()167   virtual void DetachAllSnapshots() override { MarkSnapshotIndependent(); }
168 
169   // Call to set up aContext for drawing (with the current transform, etc).
170   // Pass the path you're going to be using if you have one.
171   // Implicitly calls WillChange(aPath).
172   void PrepareForDrawing(cairo_t *aContext, const Path *aPath = nullptr);
173 
174   static cairo_surface_t *GetDummySurface();
175 
176   // Cairo hardcodes this as its maximum surface size.
GetMaxSurfaceSize()177   static size_t GetMaxSurfaceSize() { return 32767; }
178 
179  private:  // methods
180   // Init cairo surface without doing a cairo_surface_reference() call.
181   bool InitAlreadyReferenced(cairo_surface_t *aSurface, const IntSize &aSize,
182                              SurfaceFormat *aFormat = nullptr);
183   enum DrawPatternType { DRAW_FILL, DRAW_STROKE };
184   void DrawPattern(const Pattern &aPattern, const StrokeOptions &aStrokeOptions,
185                    const DrawOptions &aOptions, DrawPatternType aDrawType,
186                    bool aPathBoundsClip = false);
187 
188   void CopySurfaceInternal(cairo_surface_t *aSurface, const IntRect &aSource,
189                            const IntPoint &aDest);
190 
191   Rect GetUserSpaceClip();
192 
193   // Call before you make any changes to the backing surface with which this
194   // context is associated. Pass the path you're going to be using if you have
195   // one.
196   void WillChange(const Path *aPath = nullptr);
197 
198   // Call if there is any reason to disassociate the snapshot from this draw
199   // target; for example, because we're going to be destroyed.
200   void MarkSnapshotIndependent();
201 
202   // If the current operator is "source" then clear the destination before we
203   // draw into it, to simulate the effect of an unbounded source operator.
204   void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
205 
206   // Set the Cairo context font options according to the current draw target
207   // font state.
208   void SetFontOptions();
209 
210  private:  // data
211   cairo_t *mContext;
212   cairo_surface_t *mSurface;
213   IntSize mSize;
214   bool mTransformSingular;
215 
216   uint8_t *mLockedBits;
217 
218   cairo_font_options_t *mFontOptions;
219 
220   struct PushedLayer {
PushedLayerPushedLayer221     PushedLayer(Float aOpacity, bool aWasPermittingSubpixelAA)
222         : mOpacity(aOpacity),
223           mMaskPattern(nullptr),
224           mWasPermittingSubpixelAA(aWasPermittingSubpixelAA) {}
225     Float mOpacity;
226     cairo_pattern_t *mMaskPattern;
227     bool mWasPermittingSubpixelAA;
228   };
229   std::vector<PushedLayer> mPushedLayers;
230 
231   // The latest snapshot of this surface. This needs to be told when this
232   // target is modified. We keep it alive as a cache.
233   RefPtr<SourceSurfaceCairo> mSnapshot;
234   static cairo_surface_t *mDummySurface;
235 };
236 
237 }  // namespace gfx
238 }  // namespace mozilla
239 
240 #endif  // _MOZILLA_GFX_DRAWTARGET_CAIRO_H_
241