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 class SkDrawFilter; 20 struct SkIRect; 21 class SkMatrix; 22 class SkMetaData; 23 class SkRegion; 24 struct SkDeviceProperties; 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 explicit SkBaseDevice(const SkDeviceProperties&); 36 virtual ~SkBaseDevice(); 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 getGlobalBounds()57 SkIRect getGlobalBounds() const { 58 SkIRect bounds; 59 this->getGlobalBounds(&bounds); 60 return bounds; 61 } 62 width()63 int width() const { 64 return this->imageInfo().width(); 65 } 66 height()67 int height() const { 68 return this->imageInfo().height(); 69 } 70 isOpaque()71 bool isOpaque() const { 72 return this->imageInfo().isOpaque(); 73 } 74 75 /** Return the bitmap associated with this device. Call this each time you need 76 to access the bitmap, as it notifies the subclass to perform any flushing 77 etc. before you examine the pixels. 78 @param changePixels set to true if the caller plans to change the pixels 79 @return the device's bitmap 80 */ 81 const SkBitmap& accessBitmap(bool changePixels); 82 83 bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y); 84 85 void* accessPixels(SkImageInfo* info, size_t* rowBytes); 86 87 /** 88 * Return the device's associated gpu render target, or NULL. 89 */ accessRenderTarget()90 virtual GrRenderTarget* accessRenderTarget() { return NULL; } 91 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 99 /** 100 * onAttachToCanvas is invoked whenever a device is installed in a canvas 101 * (i.e., setDevice, saveLayer (for the new device created by the save), 102 * and SkCanvas' SkBaseDevice & SkBitmap -taking ctors). It allows the 103 * devices to prepare for drawing (e.g., locking their pixels, etc.) 104 */ onAttachToCanvas(SkCanvas *)105 virtual void onAttachToCanvas(SkCanvas*) { 106 SkASSERT(!fAttachedToCanvas); 107 this->lockPixels(); 108 #ifdef SK_DEBUG 109 fAttachedToCanvas = true; 110 #endif 111 }; 112 113 /** 114 * onDetachFromCanvas notifies a device that it will no longer be drawn to. 115 * It gives the device a chance to clean up (e.g., unlock its pixels). It 116 * is invoked from setDevice (for the displaced device), restore and 117 * possibly from SkCanvas' dtor. 118 */ onDetachFromCanvas()119 virtual void onDetachFromCanvas() { 120 SkASSERT(fAttachedToCanvas); 121 this->unlockPixels(); 122 #ifdef SK_DEBUG 123 fAttachedToCanvas = false; 124 #endif 125 }; 126 127 protected: 128 enum TileUsage { 129 kPossible_TileUsage, //!< the created device may be drawn tiled 130 kNever_TileUsage, //!< the created device will never be drawn tiled 131 }; 132 133 struct TextFlags { 134 uint32_t fFlags; // SkPaint::getFlags() 135 }; 136 137 /** 138 * Returns the text-related flags, possibly modified based on the state of the 139 * device (e.g. support for LCD). 140 */ 141 uint32_t filterTextFlags(const SkPaint&) const; 142 onShouldDisableLCD(const SkPaint &)143 virtual bool onShouldDisableLCD(const SkPaint&) const { return false; } 144 145 /** 146 * 147 * DEPRECATED: This will be removed in a future change. Device subclasses 148 * should use the matrix and clip from the SkDraw passed to draw functions. 149 * 150 * Called with the correct matrix and clip before this device is drawn 151 * to using those settings. If your subclass overrides this, be sure to 152 * call through to the base class as well. 153 * 154 * The clipstack is another view of the clip. It records the actual 155 * geometry that went into building the region. It is present for devices 156 * that want to parse it, but is not required: the region is a complete 157 * picture of the current clip. (i.e. if you regionize all of the geometry 158 * in the clipstack, you will arrive at an equivalent region to the one 159 * passed in). 160 */ setMatrixClip(const SkMatrix &,const SkRegion &,const SkClipStack &)161 virtual void setMatrixClip(const SkMatrix&, const SkRegion&, 162 const SkClipStack&) {}; 163 164 /** These are called inside the per-device-layer loop for each draw call. 165 When these are called, we have already applied any saveLayer operations, 166 and are handling any looping from the paint, and any effects from the 167 DrawFilter. 168 */ 169 virtual void drawPaint(const SkDraw&, const SkPaint& paint) = 0; 170 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, 171 const SkPoint[], const SkPaint& paint) = 0; 172 virtual void drawRect(const SkDraw&, const SkRect& r, 173 const SkPaint& paint) = 0; 174 virtual void drawOval(const SkDraw&, const SkRect& oval, 175 const SkPaint& paint) = 0; 176 virtual void drawRRect(const SkDraw&, const SkRRect& rr, 177 const SkPaint& paint) = 0; 178 179 // Default impl calls drawPath() 180 virtual void drawDRRect(const SkDraw&, const SkRRect& outer, 181 const SkRRect& inner, const SkPaint&); 182 183 /** 184 * If pathIsMutable, then the implementation is allowed to cast path to a 185 * non-const pointer and modify it in place (as an optimization). Canvas 186 * may do this to implement helpers such as drawOval, by placing a temp 187 * path on the stack to hold the representation of the oval. 188 * 189 * If prePathMatrix is not null, it should logically be applied before any 190 * stroking or other effects. If there are no effects on the paint that 191 * affect the geometry/rasterization, then the pre matrix can just be 192 * pre-concated with the current matrix. 193 */ 194 virtual void drawPath(const SkDraw&, const SkPath& path, 195 const SkPaint& paint, 196 const SkMatrix* prePathMatrix = NULL, 197 bool pathIsMutable = false) = 0; 198 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, 199 const SkMatrix& matrix, const SkPaint& paint) = 0; 200 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 201 int x, int y, const SkPaint& paint) = 0; 202 203 /** 204 * The default impl. will create a bitmap-shader from the bitmap, 205 * and call drawRect with it. 206 */ 207 virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, 208 const SkRect* srcOrNull, const SkRect& dst, 209 const SkPaint& paint, 210 SkCanvas::DrawBitmapRectFlags flags) = 0; 211 212 virtual void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&); 213 virtual void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst, 214 const SkPaint&); 215 216 /** 217 * Does not handle text decoration. 218 * Decorations (underline and stike-thru) will be handled by SkCanvas. 219 */ 220 virtual void drawText(const SkDraw&, const void* text, size_t len, 221 SkScalar x, SkScalar y, const SkPaint& paint) = 0; 222 virtual void drawPosText(const SkDraw&, const void* text, size_t len, 223 const SkScalar pos[], int scalarsPerPos, 224 const SkPoint& offset, const SkPaint& paint) = 0; 225 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, 226 const SkPoint verts[], const SkPoint texs[], 227 const SkColor colors[], SkXfermode* xmode, 228 const uint16_t indices[], int indexCount, 229 const SkPaint& paint) = 0; 230 // default implementation unrolls the blob runs. 231 virtual void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y, 232 const SkPaint& paint, SkDrawFilter* drawFilter); 233 // default implementation calls drawVertices 234 virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4], 235 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint); 236 /** The SkDevice passed will be an SkDevice which was returned by a call to 237 onCreateDevice on this device with kNeverTile_TileExpectation. 238 */ 239 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 240 const SkPaint&) = 0; 241 242 virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath&, 243 const SkMatrix*, const SkPaint&); 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 * Override and return true for filters that the device can handle 262 * intrinsically. Doing so means that SkCanvas will pass-through this 263 * filter to drawSprite and drawDevice (and potentially filterImage). 264 * Returning false means the SkCanvas will have apply the filter itself, 265 * and just pass the resulting image to the device. 266 */ canHandleImageFilter(const SkImageFilter *)267 virtual bool canHandleImageFilter(const SkImageFilter*) { return false; } 268 269 /** 270 * Related (but not required) to canHandleImageFilter, this method returns 271 * true if the device could apply the filter to the src bitmap and return 272 * the result (and updates offset as needed). 273 * If the device does not recognize or support this filter, 274 * it just returns false and leaves result and offset unchanged. 275 */ filterImage(const SkImageFilter *,const SkBitmap &,const SkImageFilter::Context &,SkBitmap *,SkIPoint *)276 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, 277 const SkImageFilter::Context&, 278 SkBitmap* /*result*/, SkIPoint* /*offset*/) { 279 return false; 280 } 281 282 protected: 283 // default impl returns NULL 284 virtual SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&); 285 286 // default impl returns NULL 287 virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes); 288 289 /** 290 * The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst 291 * image at the specified x,y offset will fit within the device's bounds. 292 * 293 * This is explicitly asserted in readPixels(), the public way to call this. 294 */ 295 virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y); 296 297 /** 298 * The caller is responsible for "pre-clipping" the src. The impl can assume that the src 299 * image at the specified x,y offset will fit within the device's bounds. 300 * 301 * This is explicitly asserted in writePixelsDirect(), the public way to call this. 302 */ 303 virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y); 304 305 /** 306 * Default impl returns NULL. 307 */ 308 virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes); 309 310 /** 311 * Leaky properties are those which the device should be applying but it isn't. 312 * These properties will be applied by the draw, when and as it can. 313 * If the device does handle a property, that property should be set to the identity value 314 * for that property, effectively making it non-leaky. 315 */ getLeakyProperties()316 const SkDeviceProperties& getLeakyProperties() const { 317 return *fLeakyProperties; 318 } 319 320 /** 321 * PRIVATE / EXPERIMENTAL -- do not call 322 * This entry point gives the backend an opportunity to take over the rendering 323 * of 'picture'. If optimization data is available (due to an earlier 324 * 'optimize' call) this entry point should make use of it and return true 325 * if all rendering has been done. If false is returned, SkCanvas will 326 * perform its own rendering pass. It is acceptable for the backend 327 * to perform some device-specific warm up tasks and then let SkCanvas 328 * perform the main rendering loop (by return false from here). 329 */ 330 virtual bool EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*, 331 const SkPaint*); 332 333 struct CreateInfo { 334 static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry); 335 336 // The constructor may change the pixel geometry based on other parameters. 337 CreateInfo(const SkImageInfo& info, 338 TileUsage tileUsage, 339 SkPixelGeometry geo, 340 bool forImageFilter = false) fInfoCreateInfo341 : fInfo(info) 342 , fTileUsage(tileUsage) 343 , fPixelGeometry(AdjustGeometry(info, tileUsage, geo)) 344 , fForImageFilter(forImageFilter) {} 345 346 const SkImageInfo fInfo; 347 const TileUsage fTileUsage; 348 const SkPixelGeometry fPixelGeometry; 349 const bool fForImageFilter; 350 }; 351 352 /** 353 * Create a new device based on CreateInfo. If the paint is not null, then it represents a 354 * preview of how the new device will be composed with its creator device (this). 355 * 356 * The subclass may be handed this device in drawDevice(), so it must always return 357 * a device that it knows how to draw, and that it knows how to identify if it is not of the 358 * same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill 359 * that contract (e.g. PDF cannot support some settings on the paint) it should return NULL, 360 * and the caller may then decide to explicitly create a bitmapdevice, knowing that later 361 * it could not call drawDevice with it (but it could call drawSprite or drawBitmap). 362 */ onCreateDevice(const CreateInfo &,const SkPaint *)363 virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) { 364 return NULL; 365 } 366 367 virtual void initForRootLayer(SkPixelGeometry geo); 368 369 private: 370 friend class SkCanvas; 371 friend struct DeviceCM; //for setMatrixClip 372 friend class SkDraw; 373 friend class SkDrawIter; 374 friend class SkDeviceFilteredPaint; 375 friend class SkDeviceImageFilterProxy; 376 friend class SkDeferredDevice; // for newSurface 377 friend class SkNoPixelsBitmapDevice; 378 379 friend class SkSurface_Raster; 380 381 // used to change the backend's pixels (and possibly config/rowbytes) 382 // but cannot change the width/height, so there should be no change to 383 // any clip information. 384 // TODO: move to SkBitmapDevice replaceBitmapBackendForRasterSurface(const SkBitmap &)385 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {} 386 forceConservativeRasterClip()387 virtual bool forceConservativeRasterClip() const { return false; } 388 389 // just called by SkCanvas when built as a layer setOrigin(int x,int y)390 void setOrigin(int x, int y) { fOrigin.set(x, y); } 391 392 /** Causes any deferred drawing to the device to be completed. 393 */ flush()394 virtual void flush() {} 395 getImageFilterCache()396 virtual SkImageFilter::Cache* getImageFilterCache() { return NULL; } 397 398 SkIPoint fOrigin; 399 SkMetaData* fMetaData; 400 SkDeviceProperties* fLeakyProperties; // will always exist. 401 402 #ifdef SK_DEBUG 403 bool fAttachedToCanvas; 404 #endif 405 406 typedef SkRefCnt INHERITED; 407 }; 408 409 #endif 410