• 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 "SkRefCnt.h"
12 #include "SkCanvas.h"
13 #include "SkColor.h"
14 #include "SkSurfaceProps.h"
15 
16 class SkBitmap;
17 class SkDrawFilter;
18 struct SkDrawShadowRec;
19 class SkImageFilterCache;
20 struct SkIRect;
21 class SkMatrix;
22 class SkRasterHandleAllocator;
23 class SkRegion;
24 class SkSpecialImage;
25 class GrRenderTarget;
26 
27 class SK_API 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 SkImageInfo&, const void*, size_t rowBytes, 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 
129 protected:
130     enum TileUsage {
131         kPossible_TileUsage,    //!< the created device may be drawn tiled
132         kNever_TileUsage,       //!< the created device will never be drawn tiled
133     };
134 
135     struct TextFlags {
136         uint32_t    fFlags;     // SkPaint::getFlags()
137     };
138 
139     /**
140      * Returns the text-related flags, possibly modified based on the state of the
141      * device (e.g. support for LCD).
142      */
143     uint32_t filterTextFlags(const SkPaint&) const;
144 
onShouldDisableLCD(const SkPaint &)145     virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
146 
onSave()147     virtual void onSave() {}
onRestore()148     virtual void onRestore() {}
onClipRect(const SkRect & rect,SkClipOp,bool aa)149     virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
onClipRRect(const SkRRect & rrect,SkClipOp,bool aa)150     virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
onClipPath(const SkPath & path,SkClipOp,bool aa)151     virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
onClipRegion(const SkRegion & deviceRgn,SkClipOp)152     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)153     virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {}
154     virtual bool onClipIsAA() const = 0;
155     virtual void onAsRgnClip(SkRegion*) const = 0;
156     enum ClipType {
157         kEmpty_ClipType,
158         kRect_ClipType,
159         kComplex_ClipType
160     };
161     virtual ClipType onGetClipType() const = 0;
162 
163     /** These are called inside the per-device-layer loop for each draw call.
164      When these are called, we have already applied any saveLayer operations,
165      and are handling any looping from the paint, and any effects from the
166      DrawFilter.
167      */
168     virtual void drawPaint(const SkPaint& paint) = 0;
169     virtual void drawPoints(SkCanvas::PointMode mode, size_t count,
170                             const SkPoint[], const SkPaint& paint) = 0;
171     virtual void drawRect(const SkRect& r,
172                           const SkPaint& paint) = 0;
173     virtual void drawRegion(const SkRegion& r,
174                             const SkPaint& paint);
175     virtual void drawOval(const SkRect& oval,
176                           const SkPaint& paint) = 0;
177     /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
178     virtual void drawArc(const SkRect& oval, SkScalar startAngle,
179                          SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
180     virtual void drawRRect(const SkRRect& rr,
181                            const SkPaint& paint) = 0;
182 
183     // Default impl calls drawPath()
184     virtual void drawDRRect(const SkRRect& outer,
185                             const SkRRect& inner, const SkPaint&);
186 
187     /**
188      *  If pathIsMutable, then the implementation is allowed to cast path to a
189      *  non-const pointer and modify it in place (as an optimization). Canvas
190      *  may do this to implement helpers such as drawOval, by placing a temp
191      *  path on the stack to hold the representation of the oval.
192      *
193      *  If prePathMatrix is not null, it should logically be applied before any
194      *  stroking or other effects. If there are no effects on the paint that
195      *  affect the geometry/rasterization, then the pre matrix can just be
196      *  pre-concated with the current matrix.
197      */
198     virtual void drawPath(const SkPath& path,
199                           const SkPaint& paint,
200                           const SkMatrix* prePathMatrix = NULL,
201                           bool pathIsMutable = false) = 0;
202     virtual void drawBitmap(const SkBitmap& bitmap,
203                             SkScalar x,
204                             SkScalar y,
205                             const SkPaint& paint) = 0;
206     virtual void drawSprite(const SkBitmap& bitmap,
207                             int x, int y, const SkPaint& paint) = 0;
208 
209     /**
210      *  The default impl. will create a bitmap-shader from the bitmap,
211      *  and call drawRect with it.
212      */
213     virtual void drawBitmapRect(const SkBitmap&,
214                                 const SkRect* srcOrNull, const SkRect& dst,
215                                 const SkPaint& paint,
216                                 SkCanvas::SrcRectConstraint) = 0;
217     virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center,
218                                 const SkRect& dst, const SkPaint&);
219     virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
220                                    const SkRect& dst, const SkPaint&);
221 
222     virtual void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
223     virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
224                                const SkPaint&, SkCanvas::SrcRectConstraint);
225     virtual void drawImageNine(const SkImage*, const SkIRect& center,
226                                const SkRect& dst, const SkPaint&);
227     virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&,
228                                   const SkRect& dst, const SkPaint&);
229 
230     /**
231      *  Does not handle text decoration.
232      *  Decorations (underline and stike-thru) will be handled by SkCanvas.
233      */
234     virtual void drawText(const void* text, size_t len,
235                           SkScalar x, SkScalar y, const SkPaint& paint) = 0;
236     virtual void drawPosText(const void* text, size_t len,
237                              const SkScalar pos[], int scalarsPerPos,
238                              const SkPoint& offset, const SkPaint& paint) = 0;
239     virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0;
240     virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
241 
242     // default implementation unrolls the blob runs.
243     virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
244                               const SkPaint& paint, SkDrawFilter* drawFilter);
245     // default implementation calls drawVertices
246     virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
247                            const SkPoint texCoords[4], SkBlendMode, bool interpColorsLinearly,
248                            const SkPaint& paint);
249 
250     // default implementation calls drawPath
251     virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
252                            const SkColor[], int count, SkBlendMode, const SkPaint&);
253 
drawAnnotation(const SkRect &,const char[],SkData *)254     virtual void drawAnnotation(const SkRect&, const char[], SkData*) {}
255 
256     /** The SkDevice passed will be an SkDevice which was returned by a call to
257         onCreateDevice on this device with kNeverTile_TileExpectation.
258      */
259     virtual void drawDevice(SkBaseDevice*, int x, int y,
260                             const SkPaint&) = 0;
261 
262     virtual void drawTextOnPath(const void* text, size_t len, const SkPath&,
263                                 const SkMatrix*, const SkPaint&);
264     virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[],
265                                  const SkPaint&);
266 
267     virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
268                              SkImage* clipImage, const SkMatrix& clipMatrix);
269     virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
270     virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
271     virtual sk_sp<SkSpecialImage> snapSpecial();
272 
273     bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
274 
275     ///////////////////////////////////////////////////////////////////////////
276 
context()277     virtual GrContext* context() const { return nullptr; }
278 
279     virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
onPeekPixels(SkPixmap *)280     virtual bool onPeekPixels(SkPixmap*) { return false; }
281 
282     /**
283      *  The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
284      *  image at the specified x,y offset will fit within the device's bounds.
285      *
286      *  This is explicitly asserted in readPixels(), the public way to call this.
287      */
288     virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y);
289 
290     /**
291      *  The caller is responsible for "pre-clipping" the src. The impl can assume that the src
292      *  image at the specified x,y offset will fit within the device's bounds.
293      *
294      *  This is explicitly asserted in writePixelsDirect(), the public way to call this.
295      */
296     virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y);
297 
onAccessPixels(SkPixmap *)298     virtual bool onAccessPixels(SkPixmap*) { return false; }
299 
300     struct CreateInfo {
301         static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
302                                               bool preserveLCDText);
303 
304         // The constructor may change the pixel geometry based on other parameters.
CreateInfoCreateInfo305         CreateInfo(const SkImageInfo& info,
306                    TileUsage tileUsage,
307                    SkPixelGeometry geo)
308             : fInfo(info)
309             , fTileUsage(tileUsage)
310             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
311         {}
312 
CreateInfoCreateInfo313         CreateInfo(const SkImageInfo& info,
314                    TileUsage tileUsage,
315                    SkPixelGeometry geo,
316                    bool preserveLCDText,
317                    SkRasterHandleAllocator* allocator)
318             : fInfo(info)
319             , fTileUsage(tileUsage)
320             , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
321             , fAllocator(allocator)
322         {}
323 
324         const SkImageInfo       fInfo;
325         const TileUsage         fTileUsage;
326         const SkPixelGeometry   fPixelGeometry;
327         SkRasterHandleAllocator* fAllocator = nullptr;
328     };
329 
330     /**
331      *  Create a new device based on CreateInfo. If the paint is not null, then it represents a
332      *  preview of how the new device will be composed with its creator device (this).
333      *
334      *  The subclass may be handed this device in drawDevice(), so it must always return
335      *  a device that it knows how to draw, and that it knows how to identify if it is not of the
336      *  same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
337      *  that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
338      *  and the caller may then decide to explicitly create a bitmapdevice, knowing that later
339      *  it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
340      */
onCreateDevice(const CreateInfo &,const SkPaint *)341     virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
342         return NULL;
343     }
344 
345     // A helper function used by derived classes to log the scale factor of a bitmap or image draw.
346     static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality);
347 
348 private:
349     friend class SkCanvas;
350     friend struct DeviceCM; //for setMatrixClip
351     friend class SkDraw;
352     friend class SkDrawIter;
353     friend class SkDeviceFilteredPaint;
354     friend class SkNoPixelsBitmapDevice;
355     friend class SkSurface_Raster;
356     friend class DeviceTestingAccess;
357 
358     // used to change the backend's pixels (and possibly config/rowbytes)
359     // but cannot change the width/height, so there should be no change to
360     // any clip information.
361     // TODO: move to SkBitmapDevice
replaceBitmapBackendForRasterSurface(const SkBitmap &)362     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
363 
forceConservativeRasterClip()364     virtual bool forceConservativeRasterClip() const { return false; }
365 
366     /**
367      * Don't call this!
368      */
accessRenderTargetContext()369     virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; }
370 
371     // just called by SkCanvas when built as a layer
372     void setOrigin(const SkMatrix& ctm, int x, int y);
373 
374     /** Causes any deferred drawing to the device to be completed.
375      */
flush()376     virtual void flush() {}
377 
getImageFilterCache()378     virtual SkImageFilterCache* getImageFilterCache() { return NULL; }
379 
380     friend class SkNoPixelsDevice;
381     friend class SkBitmapDevice;
privateResize(int w,int h)382     void privateResize(int w, int h) {
383         *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
384     }
385 
386     SkIPoint             fOrigin;
387     const SkImageInfo    fInfo;
388     const SkSurfaceProps fSurfaceProps;
389     SkMatrix             fCTM;
390 
391     typedef SkRefCnt INHERITED;
392 };
393 
394 class SkAutoDeviceCTMRestore : SkNoncopyable {
395 public:
SkAutoDeviceCTMRestore(SkBaseDevice * device,const SkMatrix & ctm)396     SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
397         : fDevice(device)
398         , fPrevCTM(device->ctm())
399     {
400         fDevice->setCTM(ctm);
401     }
~SkAutoDeviceCTMRestore()402     ~SkAutoDeviceCTMRestore() {
403         fDevice->setCTM(fPrevCTM);
404     }
405 
406 private:
407     SkBaseDevice*   fDevice;
408     const SkMatrix  fPrevCTM;
409 };
410 
411 #endif
412