• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkDevice_DEFINED
9 #define SkDevice_DEFINED
10 
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkRegion.h"
15 #include "include/core/SkSurfaceProps.h"
16 #include "include/private/SkNoncopyable.h"
17 
18 class SkBitmap;
19 struct SkDrawShadowRec;
20 class SkGlyphRun;
21 class SkGlyphRunList;
22 class SkImageFilterCache;
23 struct SkIRect;
24 class SkMatrix;
25 class SkRasterHandleAllocator;
26 class SkSpecialImage;
27 
28 class SkBaseDevice : public SkRefCnt {
29 public:
30     SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&);
31 
32     /**
33      *  Return ImageInfo for this device. If the canvas is not backed by pixels
34      *  (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
35      */
imageInfo()36     const SkImageInfo& imageInfo() const { return fInfo; }
37 
38     /**
39      *  Return SurfaceProps for this device.
40      */
surfaceProps()41     const SkSurfaceProps& surfaceProps() const {
42         return fSurfaceProps;
43     }
44 
45     /**
46      *  Return the bounds of the device in the coordinate space of the root
47      *  canvas. The root device will have its top-left at 0,0, but other devices
48      *  such as those associated with saveLayer may have a non-zero origin.
49      */
getGlobalBounds(SkIRect * bounds)50     void getGlobalBounds(SkIRect* bounds) const {
51         SkASSERT(bounds);
52         const SkIPoint& origin = this->getOrigin();
53         bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
54     }
55 
getGlobalBounds()56     SkIRect getGlobalBounds() const {
57         SkIRect bounds;
58         this->getGlobalBounds(&bounds);
59         return bounds;
60     }
61 
width()62     int width() const {
63         return this->imageInfo().width();
64     }
65 
height()66     int height() const {
67         return this->imageInfo().height();
68     }
69 
isOpaque()70     bool isOpaque() const {
71         return this->imageInfo().isOpaque();
72     }
73 
74     bool writePixels(const SkPixmap&, int x, int y);
75 
76     /**
77      *  Try to get write-access to the pixels behind the device. If successful, this returns true
78      *  and fills-out the pixmap parameter. On success it also bumps the genID of the underlying
79      *  bitmap.
80      *
81      *  On failure, returns false and ignores the pixmap parameter.
82      */
83     bool accessPixels(SkPixmap* pmap);
84 
85     /**
86      *  Try to get read-only-access to the pixels behind the device. If successful, this returns
87      *  true and fills-out the pixmap parameter.
88      *
89      *  On failure, returns false and ignores the pixmap parameter.
90      */
91     bool peekPixels(SkPixmap*);
92 
93     /**
94      *  Return the device's origin: its offset in device coordinates from
95      *  the default origin in its canvas' matrix/clip
96      */
getOrigin()97     const SkIPoint& getOrigin() const { return fOrigin; }
98 
getRasterHandle()99     virtual void* getRasterHandle() const { return nullptr; }
100 
save()101     void save() { this->onSave(); }
restore(const SkMatrix & ctm)102     void restore(const SkMatrix& ctm) {
103         this->onRestore();
104         this->setGlobalCTM(ctm);
105     }
clipRect(const SkRect & rect,SkClipOp op,bool aa)106     void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
107         this->onClipRect(rect, op, aa);
108     }
clipRRect(const SkRRect & rrect,SkClipOp op,bool aa)109     void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
110         this->onClipRRect(rrect, op, aa);
111     }
clipPath(const SkPath & path,SkClipOp op,bool aa)112     void clipPath(const SkPath& path, SkClipOp op, bool aa) {
113         this->onClipPath(path, op, aa);
114     }
clipRegion(const SkRegion & region,SkClipOp op)115     void clipRegion(const SkRegion& region, SkClipOp op) {
116         this->onClipRegion(region, op);
117     }
androidFramework_setDeviceClipRestriction(SkIRect * mutableClipRestriction)118     void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
119         this->onSetDeviceClipRestriction(mutableClipRestriction);
120     }
121     bool clipIsWideOpen() const;
122 
ctm()123     const SkMatrix& ctm() const { return fCTM; }
setCTM(const SkMatrix & ctm)124     void setCTM(const SkMatrix& ctm) {
125         fCTM = ctm;
126     }
127     void setGlobalCTM(const SkMatrix& ctm);
validateDevBounds(const SkIRect &)128     virtual void validateDevBounds(const SkIRect&) {}
129 
130 protected:
131     enum TileUsage {
132         kPossible_TileUsage,    //!< the created device may be drawn tiled
133         kNever_TileUsage,       //!< the created device will never be drawn tiled
134     };
135 
136     struct TextFlags {
137         uint32_t    fFlags;     // SkPaint::getFlags()
138     };
139 
onSave()140     virtual void onSave() {}
onRestore()141     virtual void onRestore() {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)142     virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)143     virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
onClipPath(const SkPath & path,SkClipOp,bool aa)144     virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)145     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)146     virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {}
147     virtual bool onClipIsAA() const = 0;
148     virtual void onAsRgnClip(SkRegion*) const = 0;
149     enum class ClipType {
150         kEmpty,
151         kRect,
152         kComplex
153     };
154     virtual ClipType onGetClipType() const = 0;
155 
156     /** These are called inside the per-device-layer loop for each draw call.
157      When these are called, we have already applied any saveLayer operations,
158      and are handling any looping from the paint.
159      */
160     virtual void drawPaint(const SkPaint& paint) = 0;
161     virtual void drawPoints(SkCanvas::PointMode mode, size_t count,
162                             const SkPoint[], const SkPaint& paint) = 0;
163     virtual void drawRect(const SkRect& r,
164                           const SkPaint& paint) = 0;
165     virtual void drawRegion(const SkRegion& r,
166                             const SkPaint& paint);
167     virtual void drawOval(const SkRect& oval,
168                           const SkPaint& paint) = 0;
169     /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
170     virtual void drawArc(const SkRect& oval, SkScalar startAngle,
171                          SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
172     virtual void drawRRect(const SkRRect& rr,
173                            const SkPaint& paint) = 0;
174 
175     // Default impl calls drawPath()
176     virtual void drawDRRect(const SkRRect& outer,
177                             const SkRRect& inner, const SkPaint&);
178 
179     /**
180      *  If pathIsMutable, then the implementation is allowed to cast path to a
181      *  non-const pointer and modify it in place (as an optimization). Canvas
182      *  may do this to implement helpers such as drawOval, by placing a temp
183      *  path on the stack to hold the representation of the oval.
184      */
185     virtual void drawPath(const SkPath& path,
186                           const SkPaint& paint,
187                           bool pathIsMutable = false) = 0;
188     virtual void drawSprite(const SkBitmap& bitmap,
189                             int x, int y, const SkPaint& paint) = 0;
190 
191     /**
192      *  The default impl. will create a bitmap-shader from the bitmap,
193      *  and call drawRect with it.
194      */
195     virtual void drawBitmapRect(const SkBitmap&,
196                                 const SkRect* srcOrNull, const SkRect& dst,
197                                 const SkPaint& paint,
198                                 SkCanvas::SrcRectConstraint) = 0;
199     virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center,
200                                 const SkRect& dst, const SkPaint&);
201     virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
202                                    const SkRect& dst, const SkPaint&);
203 
204     virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
205                                const SkPaint&, SkCanvas::SrcRectConstraint);
206     virtual void drawImageNine(const SkImage*, const SkIRect& center,
207                                const SkRect& dst, const SkPaint&);
208     virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
209                                   const SkRect& dst, const SkPaint&);
210 
211     virtual void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount,
212                               SkBlendMode, const SkPaint&) = 0;
213     virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
214 
215     virtual void drawGlyphRunList(const SkGlyphRunList& glyphRunList) = 0;
216     // default implementation calls drawVertices
217     virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
218                            const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint);
219 
220     // default implementation calls drawPath
221     virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
222                            const SkColor[], int count, SkBlendMode, const SkPaint&);
223 
drawAnnotation(const SkRect &,const char[],SkData *)224     virtual void drawAnnotation(const SkRect&, const char[], SkData*) {}
225 
226     // Default impl always calls drawRect() with a solid-color paint, setting it to anti-aliased
227     // only when all edge flags are set. If there's a clip region, it draws that using drawPath,
228     // or uses clipPath().
229     virtual void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
230                                 SkCanvas::QuadAAFlags aaFlags, SkColor color, SkBlendMode mode);
231     // Default impl uses drawImageRect per entry, being anti-aliased only when an entry's edge flags
232     // are all set. If there's a clip region, it will be applied using clipPath().
233     virtual void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count,
234                                     const SkPoint dstClips[], const SkMatrix preViewMatrices[],
235                                     const SkPaint& paint, SkCanvas::SrcRectConstraint);
236 
237     /** The SkDevice passed will be an SkDevice which was returned by a call to
238         onCreateDevice on this device with kNeverTile_TileExpectation.
239      */
240     virtual void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) = 0;
241 
242     void drawGlyphRunRSXform(const SkFont&, const SkGlyphID[], const SkRSXform[], int count,
243                              SkPoint origin, const SkPaint& paint);
244 
245     virtual void drawDrawable(SkDrawable*, const SkMatrix*, SkCanvas*);
246 
247     virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
248                              SkImage* clipImage, const SkMatrix& clipMatrix);
249     virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
250     virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
251     virtual sk_sp<SkSpecialImage> snapSpecial();
setImmutable()252     virtual void setImmutable() {}
253 
254     bool readPixels(const SkPixmap&, int x, int y);
255 
256     virtual sk_sp<SkSpecialImage> snapBackImage(const SkIRect&);    // default returns null
257 
258     ///////////////////////////////////////////////////////////////////////////
259 
context()260     virtual GrContext* context() const { return nullptr; }
261 
262     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
onPeekPixels(SkPixmap *)263     virtual bool onPeekPixels(SkPixmap*) { return false; }
264 
265     /**
266      *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
267      *  image at the specified x,y offset will fit within the device's bounds.
268      *
269      *  This is explicitly asserted in readPixels(), the public way to call this.
270      */
271     virtual bool onReadPixels(const SkPixmap&, int x, int y);
272 
273     /**
274      *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
275      *  image at the specified x,y offset will fit within the device's bounds.
276      *
277      *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
278      */
279     virtual bool onWritePixels(const SkPixmap&, int x, int y);
280 
onAccessPixels(SkPixmap *)281     virtual bool onAccessPixels(SkPixmap*) { return false; }
282 
283     struct CreateInfo {
284         static SkPixelGeometry AdjustGeometry(TileUsage, SkPixelGeometry);
285 
286         // The constructor may change the pixel geometry based on other parameters.
CreateInfoCreateInfo287         CreateInfo(const SkImageInfo& info,
288                    TileUsage tileUsage,
289                    SkPixelGeometry geo,
290                    bool trackCoverage,
291                    SkRasterHandleAllocator* allocator)
292             : fInfo(info)
293             , fTileUsage(tileUsage)
294             , fPixelGeometry(AdjustGeometry(tileUsage, geo))
295             , fTrackCoverage(trackCoverage)
296             , fAllocator(allocator)
297         {}
298 
299         const SkImageInfo       fInfo;
300         const TileUsage         fTileUsage;
301         const SkPixelGeometry   fPixelGeometry;
302         const bool              fTrackCoverage = false;
303         SkRasterHandleAllocator* fAllocator = nullptr;
304     };
305 
306     /**
307      *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
308      *  preview of how the new device will be composed with its creator device (this).
309      *
310      *  The subclass may be handed this device in drawDevice(), so it must always return
311      *  a device that it knows how to draw, and that it knows how to identify if it is not of the
312      *  same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
313      *  that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
314      *  and the caller may then decide to explicitly create a bitmapdevice, knowing that later
315      *  it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
316      */
onCreateDevice(const CreateInfo &,const SkPaint *)317     virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
318         return nullptr;
319     }
320 
321     // A helper function used by derived classes to log the scale factor of a bitmap or image draw.
322     static void LogDrawScaleFactor(const SkMatrix& view, const SkMatrix& srcToDst, SkFilterQuality);
323 
324 private:
325     friend class SkAndroidFrameworkUtils;
326     friend class SkCanvas;
327     friend struct DeviceCM; //for setMatrixClip
328     friend class SkDraw;
329     friend class SkDrawIter;
330     friend class SkSurface_Raster;
331     friend class DeviceTestingAccess;
332 
333     // Temporarily friend the SkGlyphRunBuilder until drawPosText is gone.
334     friend class SkGlyphRun;
335     friend class SkGlyphRunList;
336     friend class SkGlyphRunBuilder;
337 
338     // used to change the backend's pixels (and possibly config/rowbytes)
339     // but cannot change the width/height, so there should be no change to
340     // any clip information.
341     // TODO: move to SkBitmapDevice
replaceBitmapBackendForRasterSurface(const SkBitmap &)342     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
343 
forceConservativeRasterClip()344     virtual bool forceConservativeRasterClip() const { return false; }
345 
346     /**
347      * Don't call this!
348      */
accessRenderTargetContext()349     virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; }
350 
351     // just called by SkCanvas when built as a layer
352     void setOrigin(const SkMatrix& ctm, int x, int y);
353 
354     /** Causes any deferred drawing to the device to be completed.
355      */
flush()356     virtual void flush() {}
357 
getImageFilterCache()358     virtual SkImageFilterCache* getImageFilterCache() { return nullptr; }
359 
360     friend class SkNoPixelsDevice;
361     friend class SkBitmapDevice;
privateResize(int w,int h)362     void privateResize(int w, int h) {
363         *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
364     }
365 
366     SkIPoint             fOrigin;
367     const SkImageInfo    fInfo;
368     const SkSurfaceProps fSurfaceProps;
369     SkMatrix             fCTM;
370 
371     typedef SkRefCnt INHERITED;
372 };
373 
374 class SkNoPixelsDevice : public SkBaseDevice {
375 public:
376     SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props,
377                      sk_sp<SkColorSpace> colorSpace = nullptr)
378     : SkBaseDevice(SkImageInfo::Make(bounds.width(), bounds.height(), kUnknown_SkColorType,
379                                      kUnknown_SkAlphaType, std::move(colorSpace)), props)
380     {
381         // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
382         //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
383     }
384 
resetForNextPicture(const SkIRect & bounds)385     void resetForNextPicture(const SkIRect& bounds) {
386         //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
387         this->privateResize(bounds.width(), bounds.height());
388     }
389 
390 protected:
391     // We don't track the clip at all (for performance), but we have to respond to some queries.
392     // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
onSave()393     void onSave() override {}
onRestore()394     void onRestore() override {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)395     void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)396     void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
onClipPath(const SkPath & path,SkClipOp,bool aa)397     void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)398     void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)399     void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
onClipIsAA()400     bool onClipIsAA() const override { return false; }
onAsRgnClip(SkRegion * rgn)401     void onAsRgnClip(SkRegion* rgn) const override {
402         rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
403     }
onGetClipType()404     ClipType onGetClipType() const override {
405         return ClipType::kRect;
406     }
407 
drawPaint(const SkPaint & paint)408     void drawPaint(const SkPaint& paint) override {}
drawPoints(SkCanvas::PointMode,size_t,const SkPoint[],const SkPaint &)409     void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
drawRect(const SkRect &,const SkPaint &)410     void drawRect(const SkRect&, const SkPaint&) override {}
drawOval(const SkRect &,const SkPaint &)411     void drawOval(const SkRect&, const SkPaint&) override {}
drawRRect(const SkRRect &,const SkPaint &)412     void drawRRect(const SkRRect&, const SkPaint&) override {}
drawPath(const SkPath &,const SkPaint &,bool)413     void drawPath(const SkPath&, const SkPaint&, bool) override {}
drawSprite(const SkBitmap &,int,int,const SkPaint &)414     void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
drawBitmapRect(const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::SrcRectConstraint)415     void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
416                         SkCanvas::SrcRectConstraint) override {}
drawDevice(SkBaseDevice *,int,int,const SkPaint &)417     void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
drawGlyphRunList(const SkGlyphRunList & glyphRunList)418     void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override {}
drawVertices(const SkVertices *,const SkVertices::Bone[],int,SkBlendMode,const SkPaint &)419     void drawVertices(const SkVertices*, const SkVertices::Bone[], int, SkBlendMode,
420                       const SkPaint&) override {}
421 
422 private:
423     typedef SkBaseDevice INHERITED;
424 };
425 
426 class SkAutoDeviceCTMRestore : SkNoncopyable {
427 public:
SkAutoDeviceCTMRestore(SkBaseDevice * device,const SkMatrix & ctm)428     SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
429         : fDevice(device)
430         , fPrevCTM(device->ctm())
431     {
432         fDevice->setCTM(ctm);
433     }
~SkAutoDeviceCTMRestore()434     ~SkAutoDeviceCTMRestore() {
435         fDevice->setCTM(fPrevCTM);
436     }
437 
438 private:
439     SkBaseDevice*   fDevice;
440     const SkMatrix  fPrevCTM;
441 };
442 
443 #endif
444