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