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_DRAWTARGETTILED_H_
8 #define MOZILLA_GFX_DRAWTARGETTILED_H_
9 
10 #include "2D.h"
11 
12 #include "mozilla/Vector.h"
13 
14 #include "Filters.h"
15 #include "Logging.h"
16 
17 #include <vector>
18 
19 namespace mozilla {
20 namespace gfx {
21 
22 struct TileInternal : public Tile {
TileInternalTileInternal23   TileInternal() : mClippedOut(false) {}
24 
TileInternalTileInternal25   explicit TileInternal(const Tile& aOther)
26       : Tile(aOther), mClippedOut(false) {}
27 
28   bool mClippedOut;
29 };
30 
31 class DrawTargetTiled : public DrawTarget {
32  public:
33   DrawTargetTiled();
34 
35   bool Init(const TileSet& mTiles);
36 
IsTiledDrawTarget()37   bool IsTiledDrawTarget() const override { return true; }
38 
IsCaptureDT()39   bool IsCaptureDT() const override {
40     return mTiles[0].mDrawTarget->IsCaptureDT();
41   }
GetType()42   DrawTargetType GetType() const override {
43     return mTiles[0].mDrawTarget->GetType();
44   }
GetBackendType()45   BackendType GetBackendType() const override {
46     return mTiles[0].mDrawTarget->GetBackendType();
47   }
48   already_AddRefed<SourceSurface> Snapshot() override;
49   void DetachAllSnapshots() override;
GetSize()50   IntSize GetSize() const override {
51     MOZ_ASSERT(mRect.Width() > 0 && mRect.Height() > 0);
52     return IntSize(mRect.XMost(), mRect.YMost());
53   }
GetRect()54   IntRect GetRect() const override { return mRect; }
55 
56   void Flush() override;
57   void DrawSurface(SourceSurface* aSurface, const Rect& aDest,
58                    const Rect& aSource, const DrawSurfaceOptions& aSurfOptions,
59                    const DrawOptions& aOptions) override;
60   void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
61                   const Point& aDestPoint,
62                   const DrawOptions& aOptions = DrawOptions()) override;
DrawSurfaceWithShadow(SourceSurface * aSurface,const Point & aDest,const DeviceColor & aColor,const Point & aOffset,Float aSigma,CompositionOp aOperator)63   void DrawSurfaceWithShadow(
64       SourceSurface* aSurface, const Point& aDest, const DeviceColor& aColor,
65       const Point& aOffset, Float aSigma,
66       CompositionOp aOperator) override { /* Not implemented */
67     MOZ_CRASH("GFX: DrawSurfaceWithShadow");
68   }
69 
70   void ClearRect(const Rect& aRect) override;
71   void MaskSurface(const Pattern& aSource, SourceSurface* aMask, Point aOffset,
72                    const DrawOptions& aOptions = DrawOptions()) override;
73 
74   void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
75                    const IntPoint& aDestination) override;
76 
77   void FillRect(const Rect& aRect, const Pattern& aPattern,
78                 const DrawOptions& aOptions = DrawOptions()) override;
79   void StrokeRect(const Rect& aRect, const Pattern& aPattern,
80                   const StrokeOptions& aStrokeOptions = StrokeOptions(),
81                   const DrawOptions& aOptions = DrawOptions()) override;
82   void StrokeLine(const Point& aStart, const Point& aEnd,
83                   const Pattern& aPattern,
84                   const StrokeOptions& aStrokeOptions = StrokeOptions(),
85                   const DrawOptions& aOptions = DrawOptions()) override;
86   void Stroke(const Path* aPath, const Pattern& aPattern,
87               const StrokeOptions& aStrokeOptions = StrokeOptions(),
88               const DrawOptions& aOptions = DrawOptions()) override;
89   void Fill(const Path* aPath, const Pattern& aPattern,
90             const DrawOptions& aOptions = DrawOptions()) override;
91   void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
92                   const Pattern& aPattern,
93                   const DrawOptions& aOptions = DrawOptions()) override;
94   void Mask(const Pattern& aSource, const Pattern& aMask,
95             const DrawOptions& aOptions = DrawOptions()) override;
96   void PushClip(const Path* aPath) override;
97   void PushClipRect(const Rect& aRect) override;
98   void PopClip() override;
99   void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
100                  const Matrix& aMaskTransform,
101                  const IntRect& aBounds = IntRect(),
102                  bool aCopyBackground = false) override;
103   void PushLayerWithBlend(bool aOpaque, Float aOpacity, SourceSurface* aMask,
104                           const Matrix& aMaskTransform,
105                           const IntRect& aBounds = IntRect(),
106                           bool aCopyBackground = false,
107                           CompositionOp = CompositionOp::OP_OVER) override;
108   void PopLayer() override;
109 
110   void PadEdges(const IntRegion& aRegion) override;
111 
112   void SetTransform(const Matrix& aTransform) override;
113 
114   void SetPermitSubpixelAA(bool aPermitSubpixelAA) override;
115 
CreateSourceSurfaceFromData(unsigned char * aData,const IntSize & aSize,int32_t aStride,SurfaceFormat aFormat)116   already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
117       unsigned char* aData, const IntSize& aSize, int32_t aStride,
118       SurfaceFormat aFormat) const override {
119     return mTiles[0].mDrawTarget->CreateSourceSurfaceFromData(aData, aSize,
120                                                               aStride, aFormat);
121   }
OptimizeSourceSurface(SourceSurface * aSurface)122   already_AddRefed<SourceSurface> OptimizeSourceSurface(
123       SourceSurface* aSurface) const override {
124     return mTiles[0].mDrawTarget->OptimizeSourceSurface(aSurface);
125   }
126 
CreateSourceSurfaceFromNativeSurface(const NativeSurface & aSurface)127   already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
128       const NativeSurface& aSurface) const override {
129     return mTiles[0].mDrawTarget->CreateSourceSurfaceFromNativeSurface(
130         aSurface);
131   }
132 
CreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat)133   already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
134       const IntSize& aSize, SurfaceFormat aFormat) const override {
135     return mTiles[0].mDrawTarget->CreateSimilarDrawTarget(aSize, aFormat);
136   }
137 
CanCreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat)138   bool CanCreateSimilarDrawTarget(const IntSize& aSize,
139                                   SurfaceFormat aFormat) const override {
140     return mTiles[0].mDrawTarget->CanCreateSimilarDrawTarget(aSize, aFormat);
141   }
142 
143   RefPtr<DrawTarget> CreateClippedDrawTarget(const Rect& aBounds,
144                                              SurfaceFormat aFormat) override;
145 
146   already_AddRefed<PathBuilder> CreatePathBuilder(
147       FillRule aFillRule = FillRule::FILL_WINDING) const override {
148     return mTiles[0].mDrawTarget->CreatePathBuilder(aFillRule);
149   }
150 
151   already_AddRefed<GradientStops> CreateGradientStops(
152       GradientStop* aStops, uint32_t aNumStops,
153       ExtendMode aExtendMode = ExtendMode::CLAMP) const override {
154     return mTiles[0].mDrawTarget->CreateGradientStops(aStops, aNumStops,
155                                                       aExtendMode);
156   }
CreateFilter(FilterType aType)157   already_AddRefed<FilterNode> CreateFilter(FilterType aType) override {
158     return mTiles[0].mDrawTarget->CreateFilter(aType);
159   }
160 
161  private:
162   std::vector<TileInternal> mTiles;
163 
164   // mClippedOutTilesStack[clipIndex][tileIndex] is true if the tile at
165   // tileIndex has become completely clipped out at the clip stack depth
166   // clipIndex.
167   Vector<std::vector<bool>, 8> mClippedOutTilesStack;
168 
169   IntRect mRect;
170 
171   struct PushedLayer {
PushedLayerPushedLayer172     explicit PushedLayer(bool aOldPermitSubpixelAA)
173         : mOldPermitSubpixelAA(aOldPermitSubpixelAA) {}
174     bool mOldPermitSubpixelAA;
175   };
176   std::vector<PushedLayer> mPushedLayers;
177 };
178 
179 class SnapshotTiled : public SourceSurface {
180  public:
SnapshotTiled(const std::vector<TileInternal> & aTiles,const IntRect & aRect)181   SnapshotTiled(const std::vector<TileInternal>& aTiles, const IntRect& aRect)
182       : mRect(aRect) {
183     for (size_t i = 0; i < aTiles.size(); i++) {
184       mSnapshots.push_back(aTiles[i].mDrawTarget->Snapshot());
185       mOrigins.push_back(aTiles[i].mTileOrigin);
186     }
187   }
188 
GetType()189   SurfaceType GetType() const override { return SurfaceType::TILED; }
GetSize()190   IntSize GetSize() const override {
191     MOZ_ASSERT(mRect.Width() > 0 && mRect.Height() > 0);
192     return IntSize(mRect.XMost(), mRect.YMost());
193   }
GetRect()194   IntRect GetRect() const override { return mRect; }
GetFormat()195   SurfaceFormat GetFormat() const override {
196     return mSnapshots[0]->GetFormat();
197   }
198 
GetDataSurface()199   already_AddRefed<DataSourceSurface> GetDataSurface() override {
200     RefPtr<DataSourceSurface> surf =
201         Factory::CreateDataSourceSurface(mRect.Size(), GetFormat());
202     if (!surf) {
203       gfxCriticalError()
204           << "DrawTargetTiled::GetDataSurface failed to allocate surface";
205       return nullptr;
206     }
207 
208     DataSourceSurface::MappedSurface mappedSurf;
209     if (!surf->Map(DataSourceSurface::MapType::WRITE, &mappedSurf)) {
210       gfxCriticalError()
211           << "DrawTargetTiled::GetDataSurface failed to map surface";
212       return nullptr;
213     }
214 
215     {
216       RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(
217           BackendType::CAIRO, mappedSurf.mData, mRect.Size(),
218           mappedSurf.mStride, GetFormat());
219 
220       if (!dt) {
221         gfxWarning() << "DrawTargetTiled::GetDataSurface failed in "
222                         "CreateDrawTargetForData";
223         surf->Unmap();
224         return nullptr;
225       }
226       for (size_t i = 0; i < mSnapshots.size(); i++) {
227         RefPtr<DataSourceSurface> dataSurf = mSnapshots[i]->GetDataSurface();
228         dt->CopySurface(dataSurf,
229                         IntRect(IntPoint(0, 0), mSnapshots[i]->GetSize()),
230                         mOrigins[i] - mRect.TopLeft());
231       }
232     }
233     surf->Unmap();
234 
235     return surf.forget();
236   }
237 
238   std::vector<RefPtr<SourceSurface>> mSnapshots;
239   std::vector<IntPoint> mOrigins;
240   IntRect mRect;
241 };
242 
243 }  // namespace gfx
244 }  // namespace mozilla
245 
246 #endif
247