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_DRAWTARGETCAPTURE_H_
8 #define MOZILLA_GFX_DRAWTARGETCAPTURE_H_
9 
10 #include <vector>
11 #include <stack>
12 
13 #include "2D.h"
14 #include "CaptureCommandList.h"
15 
16 #include "Filters.h"
17 
18 namespace mozilla {
19 namespace gfx {
20 
21 class DrawingCommand;
22 class SourceSurfaceCapture;
23 class AlphaBoxBlur;
24 
25 class DrawTargetCaptureImpl final : public DrawTargetCapture {
26   friend class SourceSurfaceCapture;
27 
28  public:
29   DrawTargetCaptureImpl(gfx::DrawTarget* aTarget, size_t aFlushBytes);
30   DrawTargetCaptureImpl(BackendType aBackend, const IntSize& aSize,
31                         SurfaceFormat aFormat);
32 
33   bool Init(const IntSize& aSize, DrawTarget* aRefDT);
34   void InitForData(int32_t aStride, size_t aSurfaceAllocationSize);
35 
GetBackendType()36   BackendType GetBackendType() const override {
37     return mRefDT->GetBackendType();
38   }
GetType()39   DrawTargetType GetType() const override { return mRefDT->GetType(); }
IsCaptureDT()40   bool IsCaptureDT() const override { return true; }
41   already_AddRefed<SourceSurface> Snapshot() override;
42   already_AddRefed<SourceSurface> IntoLuminanceSource(
43       LuminanceType aLuminanceType, float aOpacity) override;
44   void SetPermitSubpixelAA(bool aPermitSubpixelAA) override;
45   void DetachAllSnapshots() override;
GetSize()46   IntSize GetSize() const override { return mSize; }
Flush()47   void Flush() override {}
48   void DrawSurface(SourceSurface* aSurface, const Rect& aDest,
49                    const Rect& aSource, const DrawSurfaceOptions& aSurfOptions,
50                    const DrawOptions& aOptions) override;
51   void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
52                   const Point& aDestPoint,
53                   const DrawOptions& aOptions = DrawOptions()) override;
54   void DrawSurfaceWithShadow(SourceSurface* aSurface, const Point& aDest,
55                              const DeviceColor& aColor, const Point& aOffset,
56                              Float aSigma, CompositionOp aOperator) override;
57 
58   void ClearRect(const Rect& aRect) override;
59   void MaskSurface(const Pattern& aSource, SourceSurface* aMask, Point aOffset,
60                    const DrawOptions& aOptions = DrawOptions()) override;
61   void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
62                    const IntPoint& aDestination) override;
63   void CopyRect(const IntRect& aSourceRect,
64                 const IntPoint& aDestination) override;
65 
66   void FillRect(const Rect& aRect, const Pattern& aPattern,
67                 const DrawOptions& aOptions = DrawOptions()) override;
68   void FillRoundedRect(const RoundedRect& aRect, const Pattern& aPattern,
69                        const DrawOptions& aOptions = DrawOptions()) override;
70   void StrokeRect(const Rect& aRect, const Pattern& aPattern,
71                   const StrokeOptions& aStrokeOptions = StrokeOptions(),
72                   const DrawOptions& aOptions = DrawOptions()) override;
73   void StrokeLine(const Point& aStart, const Point& aEnd,
74                   const Pattern& aPattern,
75                   const StrokeOptions& aStrokeOptions = StrokeOptions(),
76                   const DrawOptions& aOptions = DrawOptions()) override;
77   void Stroke(const Path* aPath, const Pattern& aPattern,
78               const StrokeOptions& aStrokeOptions = StrokeOptions(),
79               const DrawOptions& aOptions = DrawOptions()) override;
80   void Fill(const Path* aPath, const Pattern& aPattern,
81             const DrawOptions& aOptions = DrawOptions()) override;
82   void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
83                   const Pattern& aPattern,
84                   const DrawOptions& aOptions = DrawOptions()) override;
85   void StrokeGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
86                     const Pattern& aPattern,
87                     const StrokeOptions& aStrokeOptions = StrokeOptions(),
88                     const DrawOptions& aOptions = DrawOptions()) override;
89   void Mask(const Pattern& aSource, const Pattern& aMask,
90             const DrawOptions& aOptions = DrawOptions()) override;
91   void PushClip(const Path* aPath) override;
92   void PushClipRect(const Rect& aRect) override;
93   void PopClip() override;
94   void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
95                  const Matrix& aMaskTransform, const IntRect& aBounds,
96                  bool aCopyBackground) override;
97   void PopLayer() override;
98   void Blur(const AlphaBoxBlur& aBlur) override;
99   void PadEdges(const IntRegion& aRegion) override;
100 
101   void SetTransform(const Matrix& aTransform) override;
102 
SupportsRegionClipping()103   bool SupportsRegionClipping() const override {
104     return mRefDT->SupportsRegionClipping();
105   }
106 
CreateSourceSurfaceFromData(unsigned char * aData,const IntSize & aSize,int32_t aStride,SurfaceFormat aFormat)107   already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
108       unsigned char* aData, const IntSize& aSize, int32_t aStride,
109       SurfaceFormat aFormat) const override {
110     return mRefDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat);
111   }
112   already_AddRefed<SourceSurface> OptimizeSourceSurface(
113       SourceSurface* aSurface) const override;
114 
CreateSourceSurfaceFromNativeSurface(const NativeSurface & aSurface)115   already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
116       const NativeSurface& aSurface) const override {
117     return mRefDT->CreateSourceSurfaceFromNativeSurface(aSurface);
118   }
119 
120   already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
121       const IntSize& aSize, SurfaceFormat aFormat) const override;
122   RefPtr<DrawTarget> CreateSimilarRasterTarget(
123       const IntSize& aSize, SurfaceFormat aFormat) const override;
124   RefPtr<DrawTarget> CreateClippedDrawTarget(const Rect& aBounds,
125                                              SurfaceFormat aFormat) override;
126 
127   already_AddRefed<PathBuilder> CreatePathBuilder(
128       FillRule aFillRule = FillRule::FILL_WINDING) const override;
129 
130   already_AddRefed<GradientStops> CreateGradientStops(
131       GradientStop* aStops, uint32_t aNumStops,
132       ExtendMode aExtendMode = ExtendMode::CLAMP) const override {
133     return mRefDT->CreateGradientStops(aStops, aNumStops, aExtendMode);
134   }
135   already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
136 
137   void ReplayToDrawTarget(DrawTarget* aDT, const Matrix& aTransform);
138 
139   bool IsEmpty() const override;
140   void Dump() override;
141 
142  protected:
143   virtual ~DrawTargetCaptureImpl();
144 
145   void MarkChanged();
146 
147  private:
FlushCommandBuffer()148   void FlushCommandBuffer() {
149     ReplayToDrawTarget(mRefDT, Matrix());
150     mCommands.Clear();
151   }
152 
153   // This storage system was used to minimize the amount of heap allocations
154   // that are required while recording. It should be noted there's no
155   // guarantees on the alignments of DrawingCommands allocated in this array.
156   template <typename T>
AppendToCommandList()157   T* AppendToCommandList() {
158     if (T::AffectsSnapshot) {
159       MarkChanged();
160     }
161     if (mFlushBytes && mCommands.BufferWillAlloc<T>() &&
162         mCommands.BufferCapacity() > mFlushBytes) {
163       FlushCommandBuffer();
164     }
165     return mCommands.Append<T>();
166   }
167   template <typename T>
ReuseOrAppendToCommandList()168   T* ReuseOrAppendToCommandList() {
169     if (T::AffectsSnapshot) {
170       MarkChanged();
171     }
172     if (mFlushBytes && mCommands.BufferWillAlloc<T>() &&
173         mCommands.BufferCapacity() > mFlushBytes) {
174       FlushCommandBuffer();
175     }
176     return mCommands.ReuseOrAppend<T>();
177   }
178 
179   RefPtr<DrawTarget> mRefDT;
180   IntSize mSize;
181   RefPtr<SourceSurfaceCapture> mSnapshot;
182 
183   // These are set if the draw target must be explicitly backed by data.
184   int32_t mStride;
185   size_t mSurfaceAllocationSize;
186 
187   struct PushedLayer {
PushedLayerPushedLayer188     explicit PushedLayer(bool aOldPermitSubpixelAA)
189         : mOldPermitSubpixelAA(aOldPermitSubpixelAA) {}
190     bool mOldPermitSubpixelAA;
191   };
192   std::vector<PushedLayer> mPushedLayers;
193   std::stack<IntRect> mCurrentClipBounds;
194 
195   CaptureCommandList mCommands;
196   size_t mFlushBytes;
197 };
198 
199 }  // namespace gfx
200 }  // namespace mozilla
201 
202 #endif /* MOZILLA_GFX_DRAWTARGETCAPTURE_H_ */
203