SkDevice.h revision a1c3d78f224874833920c8017f4287a3ec538779
1 2/* 3 * Copyright 2010 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#ifndef SkDevice_DEFINED 11#define SkDevice_DEFINED 12 13#include "SkRefCnt.h" 14#include "SkBitmap.h" 15#include "SkCanvas.h" 16#include "SkColor.h" 17 18class SkClipStack; 19class SkDraw; 20struct SkIRect; 21class SkMatrix; 22class SkMetaData; 23class SkRegion; 24 25// This is an opaque class, not interpreted by skia 26class SkGpuRenderTarget; 27 28class SK_API SkDevice : public SkRefCnt { 29public: 30 SK_DECLARE_INST_COUNT(SkDevice) 31 32 /** 33 * Construct a new device with the specified bitmap as its backend. It is 34 * valid for the bitmap to have no pixels associated with it. In that case, 35 * any drawing to this device will have no effect. 36 */ 37 SkDevice(const SkBitmap& bitmap); 38 39 /** 40 * Create a new raster device and have the pixels be automatically 41 * allocated. The rowBytes of the device will be computed automatically 42 * based on the config and the width. 43 * 44 * @param config The desired config for the pixels. If the request cannot 45 * be met, the closest matching support config will be used. 46 * @param width width (in pixels) of the device 47 * @param height height (in pixels) of the device 48 * @param isOpaque Set to true if it is known that all of the pixels will 49 * be drawn to opaquely. Used as an accelerator when drawing 50 * these pixels to another device. 51 */ 52 SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false); 53 54 virtual ~SkDevice(); 55 56 /** 57 * Creates a device that is of the same type as this device (e.g. SW-raster, 58 * GPU, or PDF). The backing store for this device is created automatically 59 * (e.g. offscreen pixels or FBO or whatever is appropriate). 60 * 61 * @param width width of the device to create 62 * @param height height of the device to create 63 * @param isOpaque performance hint, set to true if you know that you will 64 * draw into this device such that all of the pixels will 65 * be opaque. 66 */ 67 SkDevice* createCompatibleDevice(SkBitmap::Config config, 68 int width, int height, 69 bool isOpaque); 70 71 SkMetaData& getMetaData(); 72 73 enum Capabilities { 74 kGL_Capability = 0x1, //!< mask indicating GL support 75 kVector_Capability = 0x2, //!< mask indicating a vector representation 76 kAll_Capabilities = 0x3 77 }; 78 virtual uint32_t getDeviceCapabilities() { return 0; } 79 80 /** Return the width of the device (in pixels). 81 */ 82 virtual int width() const { return fBitmap.width(); } 83 /** Return the height of the device (in pixels). 84 */ 85 virtual int height() const { return fBitmap.height(); } 86 87 /** 88 * Return the bounds of the device in the coordinate space of the root 89 * canvas. The root device will have its top-left at 0,0, but other devices 90 * such as those associated with saveLayer may have a non-zero origin. 91 */ 92 void getGlobalBounds(SkIRect* bounds) const; 93 94 /** Returns true if the device's bitmap's config treats every pixels as 95 implicitly opaque. 96 */ 97 bool isOpaque() const { return fBitmap.isOpaque(); } 98 99 /** Return the bitmap config of the device's pixels 100 */ 101 SkBitmap::Config config() const { return fBitmap.getConfig(); } 102 103 /** Return the bitmap associated with this device. Call this each time you need 104 to access the bitmap, as it notifies the subclass to perform any flushing 105 etc. before you examine the pixels. 106 @param changePixels set to true if the caller plans to change the pixels 107 @return the device's bitmap 108 */ 109 const SkBitmap& accessBitmap(bool changePixels); 110 111 /** 112 * DEPRECATED: This will be made protected once WebKit stops using it. 113 * Instead use Canvas' writePixels method. 114 * 115 * Similar to draw sprite, this method will copy the pixels in bitmap onto 116 * the device, with the top/left corner specified by (x, y). The pixel 117 * values in the device are completely replaced: there is no blending. 118 * 119 * Currently if bitmap is backed by a texture this is a no-op. This may be 120 * relaxed in the future. 121 * 122 * If the bitmap has config kARGB_8888_Config then the config8888 param 123 * will determines how the pixel valuess are intepreted. If the bitmap is 124 * not kARGB_8888_Config then this parameter is ignored. 125 */ 126 virtual void writePixels(const SkBitmap& bitmap, int x, int y, 127 SkCanvas::Config8888 config8888 = SkCanvas::kNative_Premul_Config8888); 128 129 /** 130 * Return the device's associated gpu render target, or NULL. 131 */ 132 virtual SkGpuRenderTarget* accessRenderTarget() { return NULL; } 133 134 135 /** 136 * Return the device's origin: its offset in device coordinates from 137 * the default origin in its canvas' matrix/clip 138 */ 139 const SkIPoint& getOrigin() const { return fOrigin; } 140 141 /** 142 * onAttachToCanvas is invoked whenever a device is installed in a canvas 143 * (i.e., setDevice, saveLayer (for the new device created by the save), 144 * and SkCanvas' SkDevice & SkBitmap -taking ctors). It allows the 145 * devices to prepare for drawing (e.g., locking their pixels, etc.) 146 */ 147 virtual void onAttachToCanvas(SkCanvas* canvas) { 148 SkASSERT(!fAttachedToCanvas); 149 this->lockPixels(); 150#ifdef SK_DEBUG 151 fAttachedToCanvas = true; 152#endif 153 }; 154 155 /** 156 * onDetachFromCanvas notifies a device that it will no longer be drawn to. 157 * It gives the device a chance to clean up (e.g., unlock its pixels). It 158 * is invoked from setDevice (for the displaced device), restore and 159 * possibly from SkCanvas' dtor. 160 */ 161 virtual void onDetachFromCanvas() { 162 SkASSERT(fAttachedToCanvas); 163 this->unlockPixels(); 164#ifdef SK_DEBUG 165 fAttachedToCanvas = false; 166#endif 167 }; 168 169protected: 170 enum Usage { 171 kGeneral_Usage, 172 kSaveLayer_Usage // <! internal use only 173 }; 174 175 struct TextFlags { 176 uint32_t fFlags; // SkPaint::getFlags() 177 SkPaint::Hinting fHinting; 178 }; 179 180 /** 181 * Device may filter the text flags for drawing text here. If it wants to 182 * make a change to the specified values, it should write them into the 183 * textflags parameter (output) and return true. If the paint is fine as 184 * is, then ignore the textflags parameter and return false. 185 * 186 * The baseclass SkDevice filters based on its depth and blitters. 187 */ 188 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*); 189 190 /** Clears the entire device to the specified color (including alpha). 191 * Ignores the clip. 192 */ 193 virtual void clear(SkColor color); 194 195 /** 196 * Deprecated name for clear. 197 */ 198 void eraseColor(SkColor eraseColor) { this->clear(eraseColor); } 199 200 /** These are called inside the per-device-layer loop for each draw call. 201 When these are called, we have already applied any saveLayer operations, 202 and are handling any looping from the paint, and any effects from the 203 DrawFilter. 204 */ 205 virtual void drawPaint(const SkDraw&, const SkPaint& paint); 206 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, 207 const SkPoint[], const SkPaint& paint); 208 virtual void drawRect(const SkDraw&, const SkRect& r, 209 const SkPaint& paint); 210 /** 211 * If pathIsMutable, then the implementation is allowed to cast path to a 212 * non-const pointer and modify it in place (as an optimization). Canvas 213 * may do this to implement helpers such as drawOval, by placing a temp 214 * path on the stack to hold the representation of the oval. 215 * 216 * If prePathMatrix is not null, it should logically be applied before any 217 * stroking or other effects. If there are no effects on the paint that 218 * affect the geometry/rasterization, then the pre matrix can just be 219 * pre-concated with the current matrix. 220 */ 221 virtual void drawPath(const SkDraw&, const SkPath& path, 222 const SkPaint& paint, 223 const SkMatrix* prePathMatrix = NULL, 224 bool pathIsMutable = false); 225 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, 226 const SkIRect* srcRectOrNull, 227 const SkMatrix& matrix, const SkPaint& paint); 228 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 229 int x, int y, const SkPaint& paint); 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 239 /** 240 * Does not handle text decoration. 241 * Decorations (underline and stike-thru) will be handled by SkCanvas. 242 */ 243 virtual void drawText(const SkDraw&, const void* text, size_t len, 244 SkScalar x, SkScalar y, const SkPaint& paint); 245 virtual void drawPosText(const SkDraw&, const void* text, size_t len, 246 const SkScalar pos[], SkScalar constY, 247 int scalarsPerPos, const SkPaint& paint); 248 virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, 249 const SkPath& path, const SkMatrix* matrix, 250 const SkPaint& paint); 251#ifdef SK_BUILD_FOR_ANDROID 252 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len, 253 const SkPoint pos[], const SkPaint& paint, 254 const SkPath& path, const SkMatrix* matrix); 255#endif 256 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, 257 const SkPoint verts[], const SkPoint texs[], 258 const SkColor colors[], SkXfermode* xmode, 259 const uint16_t indices[], int indexCount, 260 const SkPaint& paint); 261 /** The SkDevice passed will be an SkDevice which was returned by a call to 262 onCreateCompatibleDevice on this device with kSaveLayer_Usage. 263 */ 264 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, 265 const SkPaint&); 266 267 /** 268 * On success (returns true), copy the device pixels into the bitmap. 269 * On failure, the bitmap parameter is left unchanged and false is 270 * returned. 271 * 272 * The device's pixels are converted to the bitmap's config. The only 273 * supported config is kARGB_8888_Config, though this is likely to be 274 * relaxed in the future. The meaning of config kARGB_8888_Config is 275 * modified by the enum param config8888. The default value interprets 276 * kARGB_8888_Config as SkPMColor 277 * 278 * If the bitmap has pixels already allocated, the device pixels will be 279 * written there. If not, bitmap->allocPixels() will be called 280 * automatically. If the bitmap is backed by a texture readPixels will 281 * fail. 282 * 283 * The actual pixels written is the intersection of the device's bounds, 284 * and the rectangle formed by the bitmap's width,height and the specified 285 * x,y. If bitmap pixels extend outside of that intersection, they will not 286 * be modified. 287 * 288 * Other failure conditions: 289 * * If the device is not a raster device (e.g. PDF) then readPixels will 290 * fail. 291 * * If bitmap is texture-backed then readPixels will fail. (This may be 292 * relaxed in the future.) 293 */ 294 bool readPixels(SkBitmap* bitmap, 295 int x, int y, 296 SkCanvas::Config8888 config8888); 297 298 /////////////////////////////////////////////////////////////////////////// 299 300 /** Update as needed the pixel value in the bitmap, so that the caller can 301 access the pixels directly. Note: only the pixels field should be 302 altered. The config/width/height/rowbytes must remain unchanged. 303 @param bitmap The device's bitmap 304 @return Echo the bitmap parameter, or an alternate (shadow) bitmap 305 maintained by the subclass. 306 */ 307 virtual const SkBitmap& onAccessBitmap(SkBitmap*); 308 309 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } 310 // just for subclasses, to assign a custom pixelref 311 SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) { 312 fBitmap.setPixelRef(pr, offset); 313 return pr; 314 } 315 316 /** 317 * Implements readPixels API. The caller will ensure that: 318 * 1. bitmap has pixel config kARGB_8888_Config. 319 * 2. bitmap has pixels. 320 * 3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is 321 * contained in the device bounds. 322 */ 323 virtual bool onReadPixels(const SkBitmap& bitmap, 324 int x, int y, 325 SkCanvas::Config8888 config8888); 326 327 /** Called when this device is installed into a Canvas. Balanaced by a call 328 to unlockPixels() when the device is removed from a Canvas. 329 */ 330 virtual void lockPixels(); 331 virtual void unlockPixels(); 332 333 /** 334 * Returns true if the device allows processing of this imagefilter. If 335 * false is returned, then the filter is ignored. This may happen for 336 * some subclasses that do not support pixel manipulations after drawing 337 * has occurred (e.g. printing). The default implementation returns true. 338 */ 339 virtual bool allowImageFilter(SkImageFilter*); 340 341 /** 342 * Override and return true for filters that the device can handle 343 * intrinsically. Doing so means that SkCanvas will pass-through this 344 * filter to drawSprite and drawDevice (and potentially filterImage). 345 * Returning false means the SkCanvas will have apply the filter itself, 346 * and just pass the resulting image to the device. 347 */ 348 virtual bool canHandleImageFilter(SkImageFilter*); 349 350 /** 351 * Related (but not required) to canHandleImageFilter, this method returns 352 * true if the device could apply the filter to the src bitmap and return 353 * the result (and updates offset as needed). 354 * If the device does not recognize or support this filter, 355 * it just returns false and leaves result and offset unchanged. 356 */ 357 virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&, 358 SkBitmap* result, SkIPoint* offset); 359 360 // This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if 361 // either is identical to kNative_Premul_Config8888. Otherwise, -1. 362 static const SkCanvas::Config8888 kPMColorAlias; 363 364private: 365 friend class SkCanvas; 366 friend class SkDraw; 367 friend class SkDrawIter; 368 friend class SkDeviceFilteredPaint; 369 friend class SkDeviceImageFilterProxy; 370 371 friend class SkSurface_Raster; 372 // used to change the backend's pixels (and possibly config/rowbytes) 373 // but cannot change the width/height, so there should be no change to 374 // any clip information. 375 void replaceBitmapBackendForRasterSurface(const SkBitmap&); 376 377 // just called by SkCanvas when built as a layer 378 void setOrigin(int x, int y) { fOrigin.set(x, y); } 379 // just called by SkCanvas for saveLayer 380 SkDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config, 381 int width, int height, 382 bool isOpaque); 383 384 /** 385 * Subclasses should override this to implement createCompatibleDevice. 386 */ 387 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, 388 int width, int height, 389 bool isOpaque, 390 Usage usage); 391 392 /** Causes any deferred drawing to the device to be completed. 393 */ 394 virtual void flush() {} 395 396 SkBitmap fBitmap; 397 SkIPoint fOrigin; 398 SkMetaData* fMetaData; 399 400#ifdef SK_DEBUG 401 bool fAttachedToCanvas; 402#endif 403 404 typedef SkRefCnt INHERITED; 405}; 406 407#endif 408