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 26 class SkBaseDevice : public SkRefCnt { 27 public: 28 SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&); 29 30 /** 31 * Return ImageInfo for this device. If the canvas is not backed by pixels 32 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType. 33 */ 34 const SkImageInfo& imageInfo() const { return fInfo; } 35 36 /** 37 * Return SurfaceProps for this device. 38 */ 39 const SkSurfaceProps& surfaceProps() const { 40 return fSurfaceProps; 41 } 42 43 /** 44 * Return the bounds of the device in the coordinate space of the root 45 * canvas. The root device will have its top-left at 0,0, but other devices 46 * such as those associated with saveLayer may have a non-zero origin. 47 */ 48 void getGlobalBounds(SkIRect* bounds) const { 49 SkASSERT(bounds); 50 const SkIPoint& origin = this->getOrigin(); 51 bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height()); 52 } 53 54 SkIRect getGlobalBounds() const { 55 SkIRect bounds; 56 this->getGlobalBounds(&bounds); 57 return bounds; 58 } 59 60 int width() const { 61 return this->imageInfo().width(); 62 } 63 64 int height() const { 65 return this->imageInfo().height(); 66 } 67 68 bool isOpaque() const { 69 return this->imageInfo().isOpaque(); 70 } 71 72 bool writePixels(const SkPixmap&, int x, int y); 73 74 /** 75 * Try to get write-access to the pixels behind the device. If successful, this returns true 76 * and fills-out the pixmap parameter. On success it also bumps the genID of the underlying 77 * bitmap. 78 * 79 * On failure, returns false and ignores the pixmap parameter. 80 */ 81 bool accessPixels(SkPixmap* pmap); 82 83 /** 84 * Try to get read-only-access to the pixels behind the device. If successful, this returns 85 * true and fills-out the pixmap parameter. 86 * 87 * On failure, returns false and ignores the pixmap parameter. 88 */ 89 bool peekPixels(SkPixmap*); 90 91 /** 92 * Return the device's origin: its offset in device coordinates from 93 * the default origin in its canvas' matrix/clip 94 */ 95 const SkIPoint& getOrigin() const { return fOrigin; } 96 97 virtual void* getRasterHandle() const { return nullptr; } 98 99 void save() { this->onSave(); } 100 void restore(const SkMatrix& ctm) { 101 this->onRestore(); 102 this->setGlobalCTM(ctm); 103 } 104 void clipRect(const SkRect& rect, SkClipOp op, bool aa) { 105 this->onClipRect(rect, op, aa); 106 } 107 void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { 108 this->onClipRRect(rrect, op, aa); 109 } 110 void clipPath(const SkPath& path, SkClipOp op, bool aa) { 111 this->onClipPath(path, op, aa); 112 } 113 void clipRegion(const SkRegion& region, SkClipOp op) { 114 this->onClipRegion(region, op); 115 } 116 void androidFramework_setDeviceClipRestriction(SkIRect* mutableClipRestriction) { 117 this->onSetDeviceClipRestriction(mutableClipRestriction); 118 } 119 bool clipIsWideOpen() const; 120 121 const SkMatrix& ctm() const { return fCTM; } 122 void setCTM(const SkMatrix& ctm) { 123 fCTM = ctm; 124 } 125 void setGlobalCTM(const SkMatrix& ctm); 126 virtual void validateDevBounds(const SkIRect&) {} 127 128 protected: 129 enum TileUsage { 130 kPossible_TileUsage, //!< the created device may be drawn tiled 131 kNever_TileUsage, //!< the created device will never be drawn tiled 132 }; 133 134 struct TextFlags { 135 uint32_t fFlags; // SkPaint::getFlags() 136 }; 137 138 /** 139 * Returns the text-related flags, possibly modified based on the state of the 140 * device (e.g. support for LCD). 141 */ 142 uint32_t filterTextFlags(const SkPaint&) const; 143 144 virtual bool onShouldDisableLCD(const SkPaint&) const { return false; } 145 146 virtual void onSave() {} 147 virtual void onRestore() {} 148 virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {} 149 virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {} 150 virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {} 151 virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {} 152 virtual void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {} 153 virtual bool onClipIsAA() const = 0; 154 virtual void onAsRgnClip(SkRegion*) const = 0; 155 enum ClipType { 156 kEmpty_ClipType, 157 kRect_ClipType, 158 kComplex_ClipType 159 }; 160 virtual ClipType onGetClipType() const = 0; 161 162 /** These are called inside the per-device-layer loop for each draw call. 163 When these are called, we have already applied any saveLayer operations, 164 and are handling any looping from the paint, and any effects from the 165 DrawFilter. 166 */ 167 virtual void drawPaint(const SkPaint& paint) = 0; 168 virtual void drawPoints(SkCanvas::PointMode mode, size_t count, 169 const SkPoint[], const SkPaint& paint) = 0; 170 virtual void drawRect(const SkRect& r, 171 const SkPaint& paint) = 0; 172 virtual void drawRegion(const SkRegion& r, 173 const SkPaint& paint); 174 virtual void drawOval(const SkRect& oval, 175 const SkPaint& paint) = 0; 176 /** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */ 177 virtual void drawArc(const SkRect& oval, SkScalar startAngle, 178 SkScalar sweepAngle, bool useCenter, const SkPaint& paint); 179 virtual void drawRRect(const SkRRect& rr, 180 const SkPaint& paint) = 0; 181 182 // Default impl calls drawPath() 183 virtual void drawDRRect(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 SkPath& path, 198 const SkPaint& paint, 199 const SkMatrix* prePathMatrix = nullptr, 200 bool pathIsMutable = false) = 0; 201 virtual void drawBitmap(const SkBitmap& bitmap, 202 SkScalar x, 203 SkScalar y, 204 const SkPaint& paint) = 0; 205 virtual void drawSprite(const SkBitmap& bitmap, 206 int x, int y, const SkPaint& paint) = 0; 207 208 /** 209 * The default impl. will create a bitmap-shader from the bitmap, 210 * and call drawRect with it. 211 */ 212 virtual void drawBitmapRect(const SkBitmap&, 213 const SkRect* srcOrNull, const SkRect& dst, 214 const SkPaint& paint, 215 SkCanvas::SrcRectConstraint) = 0; 216 virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center, 217 const SkRect& dst, const SkPaint&); 218 virtual void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&, 219 const SkRect& dst, const SkPaint&); 220 221 virtual void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkPaint&); 222 virtual void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, 223 const SkPaint&, SkCanvas::SrcRectConstraint); 224 virtual void drawImageNine(const SkImage*, const SkIRect& center, 225 const SkRect& dst, const SkPaint&); 226 virtual void drawImageLattice(const SkImage*, const SkCanvas::Lattice&, 227 const SkRect& dst, const SkPaint&); 228 229 /** 230 * Does not handle text decoration. 231 * Decorations (underline and stike-thru) will be handled by SkCanvas. 232 */ 233 virtual void drawText(const void* text, size_t len, 234 SkScalar x, SkScalar y, const SkPaint& paint) = 0; 235 virtual void drawPosText(const void* text, size_t len, 236 const SkScalar pos[], int scalarsPerPos, 237 const SkPoint& offset, const SkPaint& paint) = 0; 238 virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0; 239 virtual void drawShadow(const SkPath&, const SkDrawShadowRec&); 240 241 // default implementation unrolls the blob runs. 242 virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, 243 const SkPaint& paint, SkDrawFilter* drawFilter); 244 // default implementation calls drawVertices 245 virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 246 const SkPoint texCoords[4], SkBlendMode, bool interpColorsLinearly, 247 const SkPaint& paint); 248 249 // default implementation calls drawPath 250 virtual void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[], 251 const SkColor[], int count, SkBlendMode, const SkPaint&); 252 253 virtual void drawAnnotation(const SkRect&, const char[], SkData*) {} 254 255 /** The SkDevice passed will be an SkDevice which was returned by a call to 256 onCreateDevice on this device with kNeverTile_TileExpectation. 257 */ 258 virtual void drawDevice(SkBaseDevice*, int x, int y, 259 const SkPaint&) = 0; 260 261 virtual void drawTextOnPath(const void* text, size_t len, const SkPath&, 262 const SkMatrix*, const SkPaint&); 263 virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[], 264 const SkPaint&); 265 266 virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&, 267 SkImage* clipImage, const SkMatrix& clipMatrix); 268 virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&); 269 virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*); 270 virtual sk_sp<SkSpecialImage> snapSpecial(); 271 272 bool readPixels(const SkPixmap&, int x, int y); 273 274 /////////////////////////////////////////////////////////////////////////// 275 276 virtual GrContext* context() const { return nullptr; } 277 278 virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&); 279 virtual bool onPeekPixels(SkPixmap*) { return false; } 280 281 /** 282 * The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst 283 * image at the specified x,y offset will fit within the device's bounds. 284 * 285 * This is explicitly asserted in readPixels(), the public way to call this. 286 */ 287 virtual bool onReadPixels(const SkPixmap&, int x, int y); 288 289 /** 290 * The caller is responsible for "pre-clipping" the src. The impl can assume that the src 291 * image at the specified x,y offset will fit within the device's bounds. 292 * 293 * This is explicitly asserted in writePixelsDirect(), the public way to call this. 294 */ 295 virtual bool onWritePixels(const SkPixmap&, int x, int y); 296 297 virtual bool onAccessPixels(SkPixmap*) { return false; } 298 299 struct CreateInfo { 300 static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry, 301 bool preserveLCDText); 302 303 // The constructor may change the pixel geometry based on other parameters. 304 CreateInfo(const SkImageInfo& info, 305 TileUsage tileUsage, 306 SkPixelGeometry geo) 307 : fInfo(info) 308 , fTileUsage(tileUsage) 309 , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false)) 310 {} 311 312 CreateInfo(const SkImageInfo& info, 313 TileUsage tileUsage, 314 SkPixelGeometry geo, 315 bool preserveLCDText, 316 SkRasterHandleAllocator* allocator) 317 : fInfo(info) 318 , fTileUsage(tileUsage) 319 , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText)) 320 , fAllocator(allocator) 321 {} 322 323 const SkImageInfo fInfo; 324 const TileUsage fTileUsage; 325 const SkPixelGeometry fPixelGeometry; 326 SkRasterHandleAllocator* fAllocator = nullptr; 327 }; 328 329 /** 330 * Create a new device based on CreateInfo. If the paint is not null, then it represents a 331 * preview of how the new device will be composed with its creator device (this). 332 * 333 * The subclass may be handed this device in drawDevice(), so it must always return 334 * a device that it knows how to draw, and that it knows how to identify if it is not of the 335 * same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill 336 * that contract (e.g. PDF cannot support some settings on the paint) it should return NULL, 337 * and the caller may then decide to explicitly create a bitmapdevice, knowing that later 338 * it could not call drawDevice with it (but it could call drawSprite or drawBitmap). 339 */ 340 virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) { 341 return nullptr; 342 } 343 344 // A helper function used by derived classes to log the scale factor of a bitmap or image draw. 345 static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality); 346 347 private: 348 friend class SkAndroidFrameworkUtils; 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 SkSurface_Raster; 355 friend class DeviceTestingAccess; 356 357 // used to change the backend's pixels (and possibly config/rowbytes) 358 // but cannot change the width/height, so there should be no change to 359 // any clip information. 360 // TODO: move to SkBitmapDevice 361 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {} 362 363 virtual bool forceConservativeRasterClip() const { return false; } 364 365 /** 366 * Don't call this! 367 */ 368 virtual GrRenderTargetContext* accessRenderTargetContext() { return nullptr; } 369 370 // just called by SkCanvas when built as a layer 371 void setOrigin(const SkMatrix& ctm, int x, int y); 372 373 /** Causes any deferred drawing to the device to be completed. 374 */ 375 virtual void flush() {} 376 377 virtual SkImageFilterCache* getImageFilterCache() { return nullptr; } 378 379 friend class SkNoPixelsDevice; 380 friend class SkBitmapDevice; 381 void privateResize(int w, int h) { 382 *const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h); 383 } 384 385 SkIPoint fOrigin; 386 const SkImageInfo fInfo; 387 const SkSurfaceProps fSurfaceProps; 388 SkMatrix fCTM; 389 390 typedef SkRefCnt INHERITED; 391 }; 392 393 class SkAutoDeviceCTMRestore : SkNoncopyable { 394 public: 395 SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm) 396 : fDevice(device) 397 , fPrevCTM(device->ctm()) 398 { 399 fDevice->setCTM(ctm); 400 } 401 ~SkAutoDeviceCTMRestore() { 402 fDevice->setCTM(fPrevCTM); 403 } 404 405 private: 406 SkBaseDevice* fDevice; 407 const SkMatrix fPrevCTM; 408 }; 409 410 #endif 411