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