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