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 "SkBitmap.h" 13 #include "SkCanvas.h" 14 #include "SkColor.h" 15 #include "SkImageFilter.h" 16 17 class SkClipStack; 18 class SkDraw; 19 struct SkIRect; 20 class SkMatrix; 21 class SkMetaData; 22 class SkRegion; 23 struct SkDeviceProperties; 24 class GrRenderTarget; 25 26 class SK_API SkBaseDevice : public SkRefCnt { 27 public: 28 SK_DECLARE_INST_COUNT(SkBaseDevice) 29 30 /** 31 * Construct a new device. 32 */ 33 SkBaseDevice(); 34 virtual ~SkBaseDevice(); 35 36 SkBaseDevice* createCompatibleDevice(const SkImageInfo&); 37 38 SkMetaData& getMetaData(); 39 40 /** 41 * Return ImageInfo for this device. If the canvas is not backed by pixels 42 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType. 43 */ 44 virtual SkImageInfo imageInfo() const; 45 46 /** 47 * Return the bounds of the device in the coordinate space of the root 48 * canvas. The root device will have its top-left at 0,0, but other devices 49 * such as those associated with saveLayer may have a non-zero origin. 50 */ getGlobalBounds(SkIRect * bounds)51 void getGlobalBounds(SkIRect* bounds) const { 52 SkASSERT(bounds); 53 const SkIPoint& origin = this->getOrigin(); 54 bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height()); 55 } 56 width()57 int width() const { 58 return this->imageInfo().width(); 59 } 60 height()61 int height() const { 62 return this->imageInfo().height(); 63 } 64 isOpaque()65 bool isOpaque() const { 66 return this->imageInfo().isOpaque(); 67 } 68 69 /** Return the bitmap associated with this device. Call this each time you need 70 to access the bitmap, as it notifies the subclass to perform any flushing 71 etc. before you examine the pixels. 72 @param changePixels set to true if the caller plans to change the pixels 73 @return the device's bitmap 74 */ 75 const SkBitmap& accessBitmap(bool changePixels); 76 77 bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y); 78 79 void* accessPixels(SkImageInfo* info, size_t* rowBytes); 80 81 /** 82 * Return the device's associated gpu render target, or NULL. 83 */ accessRenderTarget()84 virtual GrRenderTarget* accessRenderTarget() { return NULL; } 85 86 87 /** 88 * Return the device's origin: its offset in device coordinates from 89 * the default origin in its canvas' matrix/clip 90 */ getOrigin()91 const SkIPoint& getOrigin() const { return fOrigin; } 92 93 /** 94 * onAttachToCanvas is invoked whenever a device is installed in a canvas 95 * (i.e., setDevice, saveLayer (for the new device created by the save), 96 * and SkCanvas' SkBaseDevice & SkBitmap -taking ctors). It allows the 97 * devices to prepare for drawing (e.g., locking their pixels, etc.) 98 */ onAttachToCanvas(SkCanvas *)99 virtual void onAttachToCanvas(SkCanvas*) { 100 SkASSERT(!fAttachedToCanvas); 101 this->lockPixels(); 102 #ifdef SK_DEBUG 103 fAttachedToCanvas = true; 104 #endif 105 }; 106 107 /** 108 * onDetachFromCanvas notifies a device that it will no longer be drawn to. 109 * It gives the device a chance to clean up (e.g., unlock its pixels). It 110 * is invoked from setDevice (for the displaced device), restore and 111 * possibly from SkCanvas' dtor. 112 */ onDetachFromCanvas()113 virtual void onDetachFromCanvas() { 114 SkASSERT(fAttachedToCanvas); 115 this->unlockPixels(); 116 #ifdef SK_DEBUG 117 fAttachedToCanvas = false; 118 #endif 119 }; 120 121 protected: 122 enum Usage { 123 kGeneral_Usage, 124 kSaveLayer_Usage, // <! internal use only 125 kImageFilter_Usage // <! internal use only 126 }; 127 128 struct TextFlags { 129 uint32_t fFlags; // SkPaint::getFlags() 130 }; 131 132 /** 133 * Device may filter the text flags for drawing text here. If it wants to 134 * make a change to the specified values, it should write them into the 135 * textflags parameter (output) and return true. If the paint is fine as 136 * is, then ignore the textflags parameter and return false. 137 */ filterTextFlags(const SkPaint & paint,TextFlags *)138 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) { return false; } 139 140 /** 141 * 142 * DEPRECATED: This will be removed in a future change. Device subclasses 143 * should use the matrix and clip from the SkDraw passed to draw functions. 144 * 145 * Called with the correct matrix and clip before this device is drawn 146 * to using those settings. If your subclass overrides this, be sure to 147 * call through to the base class as well. 148 * 149 * The clipstack is another view of the clip. It records the actual 150 * geometry that went into building the region. It is present for devices 151 * that want to parse it, but is not required: the region is a complete 152 * picture of the current clip. (i.e. if you regionize all of the geometry 153 * in the clipstack, you will arrive at an equivalent region to the one 154 * passed in). 155 */ setMatrixClip(const SkMatrix &,const SkRegion &,const SkClipStack &)156 virtual void setMatrixClip(const SkMatrix&, const SkRegion&, 157 const SkClipStack&) {}; 158 159 /** Clears the entire device to the specified color (including alpha). 160 * Ignores the clip. 161 */ 162 virtual void clear(SkColor color) = 0; 163 164 SK_ATTR_DEPRECATED("use clear() instead") eraseColor(SkColor eraseColor)165 void eraseColor(SkColor eraseColor) { this->clear(eraseColor); } 166 167 /** These are called inside the per-device-layer loop for each draw call. 168 When these are called, we have already applied any saveLayer operations, 169 and are handling any looping from the paint, and any effects from the 170 DrawFilter. 171 */ 172 virtual void drawPaint(const SkDraw&, const SkPaint& paint) = 0; 173 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, 174 const SkPoint[], const SkPaint& paint) = 0; 175 virtual void drawRect(const SkDraw&, const SkRect& r, 176 const SkPaint& paint) = 0; 177 virtual void drawOval(const SkDraw&, const SkRect& oval, 178 const SkPaint& paint) = 0; 179 virtual void drawRRect(const SkDraw&, const SkRRect& rr, 180 const SkPaint& paint) = 0; 181 182 // Default impl calls drawPath() 183 virtual void drawDRRect(const SkDraw&, const SkRRect& outer, 184 const SkRRect& inner, const SkPaint&); 185 186 /** 187 * If pathIsMutable, then the implementation is allowed to cast path to a 188 * non-const pointer and modify it in place (as an optimization). Canvas 189 * may do this to implement helpers such as drawOval, by placing a temp 190 * path on the stack to hold the representation of the oval. 191 * 192 * If prePathMatrix is not null, it should logically be applied before any 193 * stroking or other effects. If there are no effects on the paint that 194 * affect the geometry/rasterization, then the pre matrix can just be 195 * pre-concated with the current matrix. 196 */ 197 virtual void drawPath(const SkDraw&, const SkPath& path, 198 const SkPaint& paint, 199 const SkMatrix* prePathMatrix = NULL, 200 bool pathIsMutable = false) = 0; 201 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, 202 const SkMatrix& matrix, const SkPaint& paint) = 0; 203 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 204 int x, int y, const SkPaint& paint) = 0; 205 206 /** 207 * The default impl. will create a bitmap-shader from the bitmap, 208 * and call drawRect with it. 209 */ 210 virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, 211 const SkRect* srcOrNull, const SkRect& dst, 212 const SkPaint& paint, 213 SkCanvas::DrawBitmapRectFlags flags) = 0; 214 215 /** 216 * Does not handle text decoration. 217 * Decorations (underline and stike-thru) will be handled by SkCanvas. 218 */ 219 virtual void drawText(const SkDraw&, const void* text, size_t len, 220 SkScalar x, SkScalar y, const SkPaint& paint) = 0; 221 virtual void drawPosText(const SkDraw&, const void* text, size_t len, 222 const SkScalar pos[], SkScalar constY, 223 int scalarsPerPos, const SkPaint& paint) = 0; 224 virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, 225 const SkPath& path, const SkMatrix* matrix, 226 const SkPaint& paint) = 0; 227 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, 228 const SkPoint verts[], const SkPoint texs[], 229 const SkColor colors[], SkXfermode* xmode, 230 const uint16_t indices[], int indexCount, 231 const SkPaint& paint) = 0; 232 // default implementation unrolls the blob runs. 233 virtual void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y, 234 const SkPaint& paint); 235 // default implementation calls drawVertices 236 virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4], 237 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint); 238 /** The SkDevice passed will be an SkDevice which was returned by a call to 239 onCreateDevice on this device with kSaveLayer_Usage. 240 */ 241 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 242 const SkPaint&) = 0; 243 244 bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y); 245 246 /////////////////////////////////////////////////////////////////////////// 247 248 /** Update as needed the pixel value in the bitmap, so that the caller can 249 access the pixels directly. 250 @return The device contents as a bitmap 251 */ 252 virtual const SkBitmap& onAccessBitmap() = 0; 253 254 /** Called when this device is installed into a Canvas. Balanced by a call 255 to unlockPixels() when the device is removed from a Canvas. 256 */ lockPixels()257 virtual void lockPixels() {} unlockPixels()258 virtual void unlockPixels() {} 259 260 /** 261 * Returns true if the device allows processing of this imagefilter. If 262 * false is returned, then the filter is ignored. This may happen for 263 * some subclasses that do not support pixel manipulations after drawing 264 * has occurred (e.g. printing). The default implementation returns true. 265 */ allowImageFilter(const SkImageFilter *)266 virtual bool allowImageFilter(const SkImageFilter*) { return true; } 267 268 /** 269 * Override and return true for filters that the device can handle 270 * intrinsically. Doing so means that SkCanvas will pass-through this 271 * filter to drawSprite and drawDevice (and potentially filterImage). 272 * Returning false means the SkCanvas will have apply the filter itself, 273 * and just pass the resulting image to the device. 274 */ canHandleImageFilter(const SkImageFilter *)275 virtual bool canHandleImageFilter(const SkImageFilter*) { return false; } 276 277 /** 278 * Related (but not required) to canHandleImageFilter, this method returns 279 * true if the device could apply the filter to the src bitmap and return 280 * the result (and updates offset as needed). 281 * If the device does not recognize or support this filter, 282 * it just returns false and leaves result and offset unchanged. 283 */ filterImage(const SkImageFilter *,const SkBitmap &,const SkImageFilter::Context & ctx,SkBitmap * result,SkIPoint * offset)284 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, 285 const SkImageFilter::Context& ctx, 286 SkBitmap* result, SkIPoint* offset) { 287 return false; 288 } 289 290 protected: 291 // default impl returns NULL 292 virtual SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&); 293 294 // default impl returns NULL 295 virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes); 296 297 /** 298 * The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst 299 * image at the specified x,y offset will fit within the device's bounds. 300 * 301 * This is explicitly asserted in readPixels(), the public way to call this. 302 */ 303 virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y); 304 305 /** 306 * The caller is responsible for "pre-clipping" the src. The impl can assume that the src 307 * image at the specified x,y offset will fit within the device's bounds. 308 * 309 * This is explicitly asserted in writePixelsDirect(), the public way to call this. 310 */ 311 virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y); 312 313 /** 314 * Default impl returns NULL. 315 */ 316 virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes); 317 318 /** 319 * Leaky properties are those which the device should be applying but it isn't. 320 * These properties will be applied by the draw, when and as it can. 321 * If the device does handle a property, that property should be set to the identity value 322 * for that property, effectively making it non-leaky. 323 */ getLeakyProperties()324 const SkDeviceProperties& getLeakyProperties() const { 325 return *fLeakyProperties; 326 } 327 328 /** 329 * PRIVATE / EXPERIMENTAL -- do not call 330 * Construct an acceleration object and attach it to 'picture' 331 */ 332 virtual void EXPERIMENTAL_optimize(const SkPicture* picture); 333 334 /** 335 * PRIVATE / EXPERIMENTAL -- do not call 336 * This entry point gives the backend an opportunity to take over the rendering 337 * of 'picture'. If optimization data is available (due to an earlier 338 * 'optimize' call) this entry point should make use of it and return true 339 * if all rendering has been done. If false is returned, SkCanvas will 340 * perform its own rendering pass. It is acceptable for the backend 341 * to perform some device-specific warm up tasks and then let SkCanvas 342 * perform the main rendering loop (by return false from here). 343 */ 344 virtual bool EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*, 345 const SkPaint*); 346 347 void setPixelGeometry(SkPixelGeometry geo); 348 349 private: 350 friend class SkCanvas; 351 friend struct DeviceCM; //for setMatrixClip 352 friend class SkDraw; 353 friend class SkDrawIter; 354 friend class SkDeviceFilteredPaint; 355 friend class SkDeviceImageFilterProxy; 356 friend class SkDeferredDevice; // for newSurface 357 358 friend class SkSurface_Raster; 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 // just called by SkCanvas when built as a layer setOrigin(int x,int y)369 void setOrigin(int x, int y) { fOrigin.set(x, y); } 370 // just called by SkCanvas for saveLayer 371 SkBaseDevice* createCompatibleDeviceForSaveLayer(const SkImageInfo&); 372 // just called by SkCanvas for imagefilter 373 SkBaseDevice* createCompatibleDeviceForImageFilter(const SkImageInfo&); 374 onCreateDevice(const SkImageInfo &,Usage)375 virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) { 376 return NULL; 377 } 378 379 /** Causes any deferred drawing to the device to be completed. 380 */ flush()381 virtual void flush() {} 382 getImageFilterCache()383 virtual SkImageFilter::Cache* getImageFilterCache() { return NULL; } 384 385 SkIPoint fOrigin; 386 SkMetaData* fMetaData; 387 SkDeviceProperties* fLeakyProperties; // will always exist. 388 389 #ifdef SK_DEBUG 390 bool fAttachedToCanvas; 391 #endif 392 393 typedef SkRefCnt INHERITED; 394 }; 395 396 #endif 397