1 /*
2 * Copyright 2008 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 #include "SkCanvas.h"
9 #include "SkCanvasPriv.h"
10 #include "SkBitmapDevice.h"
11 #include "SkColorFilter.h"
12 #include "SkDeviceImageFilterProxy.h"
13 #include "SkDraw.h"
14 #include "SkDrawable.h"
15 #include "SkDrawFilter.h"
16 #include "SkDrawLooper.h"
17 #include "SkErrorInternals.h"
18 #include "SkImage.h"
19 #include "SkMetaData.h"
20 #include "SkPathOps.h"
21 #include "SkPatchUtils.h"
22 #include "SkPicture.h"
23 #include "SkRasterClip.h"
24 #include "SkReadPixelsRec.h"
25 #include "SkRRect.h"
26 #include "SkSmallAllocator.h"
27 #include "SkSurface_Base.h"
28 #include "SkTemplates.h"
29 #include "SkTextBlob.h"
30 #include "SkTextFormatParams.h"
31 #include "SkTLazy.h"
32 #include "SkTraceEvent.h"
33 #include "SkUtils.h"
34
35 #if SK_SUPPORT_GPU
36 #include "GrRenderTarget.h"
37 #endif
38
39 static bool gIgnoreSaveLayerBounds;
Internal_Private_SetIgnoreSaveLayerBounds(bool ignore)40 void SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
41 gIgnoreSaveLayerBounds = ignore;
42 }
Internal_Private_GetIgnoreSaveLayerBounds()43 bool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
44 return gIgnoreSaveLayerBounds;
45 }
46
47 static bool gTreatSpriteAsBitmap;
Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap)48 void SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
49 gTreatSpriteAsBitmap = spriteAsBitmap;
50 }
Internal_Private_GetTreatSpriteAsBitmap()51 bool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
52 return gTreatSpriteAsBitmap;
53 }
54
55 // experimental for faster tiled drawing...
56 //#define SK_ENABLE_CLIP_QUICKREJECT
57
58 //#define SK_TRACE_SAVERESTORE
59
60 #ifdef SK_TRACE_SAVERESTORE
61 static int gLayerCounter;
inc_layer()62 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
dec_layer()63 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
64
65 static int gRecCounter;
inc_rec()66 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
dec_rec()67 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
68
69 static int gCanvasCounter;
inc_canvas()70 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
dec_canvas()71 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
72 #else
73 #define inc_layer()
74 #define dec_layer()
75 #define inc_rec()
76 #define dec_rec()
77 #define inc_canvas()
78 #define dec_canvas()
79 #endif
80
81 typedef SkTLazy<SkPaint> SkLazyPaint;
82
predrawNotify()83 void SkCanvas::predrawNotify() {
84 if (fSurfaceBase) {
85 fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
86 }
87 }
88
89 ///////////////////////////////////////////////////////////////////////////////
90
filter_paint_flags(const SkSurfaceProps & props,uint32_t flags)91 static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
92 const uint32_t propFlags = props.flags();
93 if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
94 flags &= ~SkPaint::kDither_Flag;
95 }
96 if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
97 flags &= ~SkPaint::kAntiAlias_Flag;
98 }
99 return flags;
100 }
101
102 ///////////////////////////////////////////////////////////////////////////////
103
104 /* This is the record we keep for each SkBaseDevice that the user installs.
105 The clip/matrix/proc are fields that reflect the top of the save/restore
106 stack. Whenever the canvas changes, it marks a dirty flag, and then before
107 these are used (assuming we're not on a layer) we rebuild these cache
108 values: they reflect the top of the save stack, but translated and clipped
109 by the device's XY offset and bitmap-bounds.
110 */
111 struct DeviceCM {
112 DeviceCM* fNext;
113 SkBaseDevice* fDevice;
114 SkRasterClip fClip;
115 SkPaint* fPaint; // may be null (in the future)
116 const SkMatrix* fMatrix;
117 SkMatrix fMatrixStorage;
118 const bool fDeviceIsBitmapDevice;
119
DeviceCMDeviceCM120 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
121 bool conservativeRasterClip, bool deviceIsBitmapDevice)
122 : fNext(NULL)
123 , fClip(conservativeRasterClip)
124 , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
125 {
126 if (NULL != device) {
127 device->ref();
128 device->onAttachToCanvas(canvas);
129 }
130 fDevice = device;
131 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
132 }
133
~DeviceCMDeviceCM134 ~DeviceCM() {
135 if (fDevice) {
136 fDevice->onDetachFromCanvas();
137 fDevice->unref();
138 }
139 SkDELETE(fPaint);
140 }
141
resetDeviceCM142 void reset(const SkIRect& bounds) {
143 SkASSERT(!fPaint);
144 SkASSERT(!fNext);
145 SkASSERT(fDevice);
146 fClip.setRect(bounds);
147 }
148
updateMCDeviceCM149 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
150 const SkClipStack& clipStack, SkRasterClip* updateClip) {
151 int x = fDevice->getOrigin().x();
152 int y = fDevice->getOrigin().y();
153 int width = fDevice->width();
154 int height = fDevice->height();
155
156 if ((x | y) == 0) {
157 fMatrix = &totalMatrix;
158 fClip = totalClip;
159 } else {
160 fMatrixStorage = totalMatrix;
161 fMatrixStorage.postTranslate(SkIntToScalar(-x),
162 SkIntToScalar(-y));
163 fMatrix = &fMatrixStorage;
164
165 totalClip.translate(-x, -y, &fClip);
166 }
167
168 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
169
170 // intersect clip, but don't translate it (yet)
171
172 if (updateClip) {
173 updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
174 SkRegion::kDifference_Op);
175 }
176
177 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
178
179 #ifdef SK_DEBUG
180 if (!fClip.isEmpty()) {
181 SkIRect deviceR;
182 deviceR.set(0, 0, width, height);
183 SkASSERT(deviceR.contains(fClip.getBounds()));
184 }
185 #endif
186 }
187 };
188
189 /* This is the record we keep for each save/restore level in the stack.
190 Since a level optionally copies the matrix and/or stack, we have pointers
191 for these fields. If the value is copied for this level, the copy is
192 stored in the ...Storage field, and the pointer points to that. If the
193 value is not copied for this level, we ignore ...Storage, and just point
194 at the corresponding value in the previous level in the stack.
195 */
196 class SkCanvas::MCRec {
197 public:
198 SkDrawFilter* fFilter; // the current filter (or null)
199 DeviceCM* fLayer;
200 /* If there are any layers in the stack, this points to the top-most
201 one that is at or below this level in the stack (so we know what
202 bitmap/device to draw into from this level. This value is NOT
203 reference counted, since the real owner is either our fLayer field,
204 or a previous one in a lower level.)
205 */
206 DeviceCM* fTopLayer;
207 SkRasterClip fRasterClip;
208 SkMatrix fMatrix;
209 int fDeferredSaveCount;
210
MCRec(bool conservativeRasterClip)211 MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
212 fFilter = NULL;
213 fLayer = NULL;
214 fTopLayer = NULL;
215 fMatrix.reset();
216 fDeferredSaveCount = 0;
217
218 // don't bother initializing fNext
219 inc_rec();
220 }
MCRec(const MCRec & prev)221 MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
222 fFilter = SkSafeRef(prev.fFilter);
223 fLayer = NULL;
224 fTopLayer = prev.fTopLayer;
225 fDeferredSaveCount = 0;
226
227 // don't bother initializing fNext
228 inc_rec();
229 }
~MCRec()230 ~MCRec() {
231 SkSafeUnref(fFilter);
232 SkDELETE(fLayer);
233 dec_rec();
234 }
235
reset(const SkIRect & bounds)236 void reset(const SkIRect& bounds) {
237 SkASSERT(fLayer);
238 SkASSERT(fDeferredSaveCount == 0);
239
240 fMatrix.reset();
241 fRasterClip.setRect(bounds);
242 fLayer->reset(bounds);
243 }
244 };
245
246 class SkDrawIter : public SkDraw {
247 public:
SkDrawIter(SkCanvas * canvas,bool skipEmptyClips=true)248 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
249 canvas = canvas->canvasForDrawIter();
250 fCanvas = canvas;
251 canvas->updateDeviceCMCache();
252
253 fClipStack = canvas->fClipStack;
254 fCurrLayer = canvas->fMCRec->fTopLayer;
255 fSkipEmptyClips = skipEmptyClips;
256 }
257
next()258 bool next() {
259 // skip over recs with empty clips
260 if (fSkipEmptyClips) {
261 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
262 fCurrLayer = fCurrLayer->fNext;
263 }
264 }
265
266 const DeviceCM* rec = fCurrLayer;
267 if (rec && rec->fDevice) {
268
269 fMatrix = rec->fMatrix;
270 fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW();
271 fRC = &rec->fClip;
272 fDevice = rec->fDevice;
273 fBitmap = &fDevice->accessBitmap(true);
274 fPaint = rec->fPaint;
275 SkDEBUGCODE(this->validate();)
276
277 fCurrLayer = rec->fNext;
278 // fCurrLayer may be NULL now
279
280 return true;
281 }
282 return false;
283 }
284
getDevice() const285 SkBaseDevice* getDevice() const { return fDevice; }
getX() const286 int getX() const { return fDevice->getOrigin().x(); }
getY() const287 int getY() const { return fDevice->getOrigin().y(); }
getMatrix() const288 const SkMatrix& getMatrix() const { return *fMatrix; }
getClip() const289 const SkRegion& getClip() const { return *fClip; }
getPaint() const290 const SkPaint* getPaint() const { return fPaint; }
291
292 private:
293 SkCanvas* fCanvas;
294 const DeviceCM* fCurrLayer;
295 const SkPaint* fPaint; // May be null.
296 SkBool8 fSkipEmptyClips;
297
298 typedef SkDraw INHERITED;
299 };
300
301 /////////////////////////////////////////////////////////////////////////////
302
set_if_needed(SkLazyPaint * lazy,const SkPaint & orig)303 static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
304 return lazy->isValid() ? lazy->get() : lazy->set(orig);
305 }
306
307 /**
308 * If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
309 * colorfilter, else return NULL.
310 */
image_to_color_filter(const SkPaint & paint)311 static SkColorFilter* image_to_color_filter(const SkPaint& paint) {
312 SkImageFilter* imgf = paint.getImageFilter();
313 if (!imgf) {
314 return NULL;
315 }
316
317 SkColorFilter* imgCF;
318 if (!imgf->asAColorFilter(&imgCF)) {
319 return NULL;
320 }
321
322 SkColorFilter* paintCF = paint.getColorFilter();
323 if (NULL == paintCF) {
324 // there is no existing paint colorfilter, so we can just return the imagefilter's
325 return imgCF;
326 }
327
328 // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
329 // and we need to combine them into a single colorfilter.
330 SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
331 return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
332 }
333
334 class AutoDrawLooper {
335 public:
AutoDrawLooper(SkCanvas * canvas,const SkSurfaceProps & props,const SkPaint & paint,bool skipLayerForImageFilter=false,const SkRect * bounds=NULL)336 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
337 bool skipLayerForImageFilter = false,
338 const SkRect* bounds = NULL) : fOrigPaint(paint) {
339 fCanvas = canvas;
340 fFilter = canvas->getDrawFilter();
341 fPaint = &fOrigPaint;
342 fSaveCount = canvas->getSaveCount();
343 fTempLayerForImageFilter = false;
344 fDone = false;
345
346 SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
347 if (simplifiedCF) {
348 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
349 paint->setColorFilter(simplifiedCF)->unref();
350 paint->setImageFilter(NULL);
351 fPaint = paint;
352 }
353
354 if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
355 /**
356 * We implement ImageFilters for a given draw by creating a layer, then applying the
357 * imagefilter to the pixels of that layer (its backing surface/image), and then
358 * we call restore() to xfer that layer to the main canvas.
359 *
360 * 1. SaveLayer (with a paint containing the current imagefilter and xfermode)
361 * 2. Generate the src pixels:
362 * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
363 * return (fPaint). We then draw the primitive (using srcover) into a cleared
364 * buffer/surface.
365 * 3. Restore the layer created in #1
366 * The imagefilter is passed the buffer/surface from the layer (now filled with the
367 * src pixels of the primitive). It returns a new "filtered" buffer, which we
368 * draw onto the previous layer using the xfermode from the original paint.
369 */
370 SkPaint tmp;
371 tmp.setImageFilter(fPaint->getImageFilter());
372 tmp.setXfermode(fPaint->getXfermode());
373 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
374 SkCanvas::kFullLayer_SaveLayerStrategy);
375 fTempLayerForImageFilter = true;
376 // we remove the imagefilter/xfermode inside doNext()
377 }
378
379 if (SkDrawLooper* looper = paint.getLooper()) {
380 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
381 looper->contextSize());
382 fLooperContext = looper->createContext(canvas, buffer);
383 fIsSimple = false;
384 } else {
385 fLooperContext = NULL;
386 // can we be marked as simple?
387 fIsSimple = !fFilter && !fTempLayerForImageFilter;
388 }
389
390 uint32_t oldFlags = paint.getFlags();
391 fNewPaintFlags = filter_paint_flags(props, oldFlags);
392 if (fIsSimple && (fNewPaintFlags != oldFlags)) {
393 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
394 paint->setFlags(fNewPaintFlags);
395 fPaint = paint;
396 // if we're not simple, doNext() will take care of calling setFlags()
397 }
398 }
399
~AutoDrawLooper()400 ~AutoDrawLooper() {
401 if (fTempLayerForImageFilter) {
402 fCanvas->internalRestore();
403 }
404 SkASSERT(fCanvas->getSaveCount() == fSaveCount);
405 }
406
paint() const407 const SkPaint& paint() const {
408 SkASSERT(fPaint);
409 return *fPaint;
410 }
411
next(SkDrawFilter::Type drawType)412 bool next(SkDrawFilter::Type drawType) {
413 if (fDone) {
414 return false;
415 } else if (fIsSimple) {
416 fDone = true;
417 return !fPaint->nothingToDraw();
418 } else {
419 return this->doNext(drawType);
420 }
421 }
422
423 private:
424 SkLazyPaint fLazyPaintInit; // base paint storage in case we need to modify it
425 SkLazyPaint fLazyPaintPerLooper; // per-draw-looper storage, so the looper can modify it
426 SkCanvas* fCanvas;
427 const SkPaint& fOrigPaint;
428 SkDrawFilter* fFilter;
429 const SkPaint* fPaint;
430 int fSaveCount;
431 uint32_t fNewPaintFlags;
432 bool fTempLayerForImageFilter;
433 bool fDone;
434 bool fIsSimple;
435 SkDrawLooper::Context* fLooperContext;
436 SkSmallAllocator<1, 32> fLooperContextAllocator;
437
438 bool doNext(SkDrawFilter::Type drawType);
439 };
440
doNext(SkDrawFilter::Type drawType)441 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
442 fPaint = NULL;
443 SkASSERT(!fIsSimple);
444 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
445
446 SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
447 *fLazyPaintInit.get() : fOrigPaint);
448 paint->setFlags(fNewPaintFlags);
449
450 if (fTempLayerForImageFilter) {
451 paint->setImageFilter(NULL);
452 paint->setXfermode(NULL);
453 }
454
455 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
456 fDone = true;
457 return false;
458 }
459 if (fFilter) {
460 if (!fFilter->filter(paint, drawType)) {
461 fDone = true;
462 return false;
463 }
464 if (NULL == fLooperContext) {
465 // no looper means we only draw once
466 fDone = true;
467 }
468 }
469 fPaint = paint;
470
471 // if we only came in here for the imagefilter, mark us as done
472 if (!fLooperContext && !fFilter) {
473 fDone = true;
474 }
475
476 // call this after any possible paint modifiers
477 if (fPaint->nothingToDraw()) {
478 fPaint = NULL;
479 return false;
480 }
481 return true;
482 }
483
484 ////////// macros to place around the internal draw calls //////////////////
485
486 #define LOOPER_BEGIN_DRAWDEVICE(paint, type) \
487 this->predrawNotify(); \
488 AutoDrawLooper looper(this, fProps, paint, true); \
489 while (looper.next(type)) { \
490 SkDrawIter iter(this);
491
492 #define LOOPER_BEGIN(paint, type, bounds) \
493 this->predrawNotify(); \
494 AutoDrawLooper looper(this, fProps, paint, false, bounds); \
495 while (looper.next(type)) { \
496 SkDrawIter iter(this);
497
498 #define LOOPER_END }
499
500 ////////////////////////////////////////////////////////////////////////////
501
resetForNextPicture(const SkIRect & bounds)502 void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
503 this->restoreToCount(1);
504 fCachedLocalClipBounds.setEmpty();
505 fCachedLocalClipBoundsDirty = true;
506 fClipStack->reset();
507 fMCRec->reset(bounds);
508
509 // We're peering through a lot of structs here. Only at this scope do we
510 // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
511 static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
512 }
513
init(SkBaseDevice * device,InitFlags flags)514 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
515 fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
516 fCachedLocalClipBounds.setEmpty();
517 fCachedLocalClipBoundsDirty = true;
518 fAllowSoftClip = true;
519 fAllowSimplifyClip = false;
520 fDeviceCMDirty = true;
521 fSaveCount = 1;
522 fMetaData = NULL;
523
524 fClipStack.reset(SkNEW(SkClipStack));
525
526 fMCRec = (MCRec*)fMCStack.push_back();
527 new (fMCRec) MCRec(fConservativeRasterClip);
528
529 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
530 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
531 new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false);
532
533 fMCRec->fTopLayer = fMCRec->fLayer;
534
535 fSurfaceBase = NULL;
536
537 if (device) {
538 device->initForRootLayer(fProps.pixelGeometry());
539 if (device->forceConservativeRasterClip()) {
540 fConservativeRasterClip = true;
541 }
542 device->onAttachToCanvas(this);
543 fMCRec->fLayer->fDevice = SkRef(device);
544 fMCRec->fRasterClip.setRect(device->getGlobalBounds());
545 }
546 return device;
547 }
548
SkCanvas()549 SkCanvas::SkCanvas()
550 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
551 , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
552 {
553 inc_canvas();
554
555 this->init(NULL, kDefault_InitFlags);
556 }
557
make_nopixels(int width,int height)558 static SkBitmap make_nopixels(int width, int height) {
559 SkBitmap bitmap;
560 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
561 return bitmap;
562 }
563
564 class SkNoPixelsBitmapDevice : public SkBitmapDevice {
565 public:
SkNoPixelsBitmapDevice(const SkIRect & bounds)566 SkNoPixelsBitmapDevice(const SkIRect& bounds)
567 : INHERITED(make_nopixels(bounds.width(), bounds.height()))
568 {
569 this->setOrigin(bounds.x(), bounds.y());
570 }
571
572 private:
573
574 typedef SkBitmapDevice INHERITED;
575 };
576
SkCanvas(int width,int height,const SkSurfaceProps * props)577 SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
578 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
579 , fProps(SkSurfacePropsCopyOrDefault(props))
580 {
581 inc_canvas();
582
583 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
584 (SkIRect::MakeWH(width, height))), kDefault_InitFlags)->unref();
585 }
586
SkCanvas(const SkIRect & bounds,InitFlags flags)587 SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
588 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
589 , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
590 {
591 inc_canvas();
592
593 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds)), flags)->unref();
594 }
595
SkCanvas(SkBaseDevice * device,const SkSurfaceProps * props,InitFlags flags)596 SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags)
597 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
598 , fProps(SkSurfacePropsCopyOrDefault(props))
599 {
600 inc_canvas();
601
602 this->init(device, flags);
603 }
604
SkCanvas(SkBaseDevice * device)605 SkCanvas::SkCanvas(SkBaseDevice* device)
606 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
607 , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
608 {
609 inc_canvas();
610
611 this->init(device, kDefault_InitFlags);
612 }
613
SkCanvas(const SkBitmap & bitmap,const SkSurfaceProps & props)614 SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
615 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
616 , fProps(props)
617 {
618 inc_canvas();
619
620 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
621 this->init(device, kDefault_InitFlags);
622 }
623
SkCanvas(const SkBitmap & bitmap)624 SkCanvas::SkCanvas(const SkBitmap& bitmap)
625 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
626 , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
627 {
628 inc_canvas();
629
630 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
631 this->init(device, kDefault_InitFlags);
632 }
633
~SkCanvas()634 SkCanvas::~SkCanvas() {
635 // free up the contents of our deque
636 this->restoreToCount(1); // restore everything but the last
637
638 this->internalRestore(); // restore the last, since we're going away
639
640 SkDELETE(fMetaData);
641
642 dec_canvas();
643 }
644
getDrawFilter() const645 SkDrawFilter* SkCanvas::getDrawFilter() const {
646 return fMCRec->fFilter;
647 }
648
setDrawFilter(SkDrawFilter * filter)649 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
650 this->checkForDeferredSave();
651 SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
652 return filter;
653 }
654
getMetaData()655 SkMetaData& SkCanvas::getMetaData() {
656 // metadata users are rare, so we lazily allocate it. If that changes we
657 // can decide to just make it a field in the device (rather than a ptr)
658 if (NULL == fMetaData) {
659 fMetaData = new SkMetaData;
660 }
661 return *fMetaData;
662 }
663
664 ///////////////////////////////////////////////////////////////////////////////
665
flush()666 void SkCanvas::flush() {
667 SkBaseDevice* device = this->getDevice();
668 if (device) {
669 device->flush();
670 }
671 }
672
getTopLayerSize() const673 SkISize SkCanvas::getTopLayerSize() const {
674 SkBaseDevice* d = this->getTopDevice();
675 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
676 }
677
getTopLayerOrigin() const678 SkIPoint SkCanvas::getTopLayerOrigin() const {
679 SkBaseDevice* d = this->getTopDevice();
680 return d ? d->getOrigin() : SkIPoint::Make(0, 0);
681 }
682
getBaseLayerSize() const683 SkISize SkCanvas::getBaseLayerSize() const {
684 SkBaseDevice* d = this->getDevice();
685 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
686 }
687
getDevice() const688 SkBaseDevice* SkCanvas::getDevice() const {
689 // return root device
690 MCRec* rec = (MCRec*) fMCStack.front();
691 SkASSERT(rec && rec->fLayer);
692 return rec->fLayer->fDevice;
693 }
694
getTopDevice(bool updateMatrixClip) const695 SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
696 if (updateMatrixClip) {
697 const_cast<SkCanvas*>(this)->updateDeviceCMCache();
698 }
699 return fMCRec->fTopLayer->fDevice;
700 }
701
readPixels(SkBitmap * bitmap,int x,int y)702 bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
703 if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
704 return false;
705 }
706
707 bool weAllocated = false;
708 if (NULL == bitmap->pixelRef()) {
709 if (!bitmap->tryAllocPixels()) {
710 return false;
711 }
712 weAllocated = true;
713 }
714
715 SkBitmap bm(*bitmap);
716 bm.lockPixels();
717 if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
718 return true;
719 }
720
721 if (weAllocated) {
722 bitmap->setPixelRef(NULL);
723 }
724 return false;
725 }
726
readPixels(const SkIRect & srcRect,SkBitmap * bitmap)727 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
728 SkIRect r = srcRect;
729 const SkISize size = this->getBaseLayerSize();
730 if (!r.intersect(0, 0, size.width(), size.height())) {
731 bitmap->reset();
732 return false;
733 }
734
735 if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
736 // bitmap will already be reset.
737 return false;
738 }
739 if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
740 bitmap->reset();
741 return false;
742 }
743 return true;
744 }
745
readPixels(const SkImageInfo & dstInfo,void * dstP,size_t rowBytes,int x,int y)746 bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
747 SkBaseDevice* device = this->getDevice();
748 if (!device) {
749 return false;
750 }
751 const SkISize size = this->getBaseLayerSize();
752
753 SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
754 if (!rec.trim(size.width(), size.height())) {
755 return false;
756 }
757
758 // The device can assert that the requested area is always contained in its bounds
759 return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
760 }
761
writePixels(const SkBitmap & bitmap,int x,int y)762 bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
763 if (bitmap.getTexture()) {
764 return false;
765 }
766 SkBitmap bm(bitmap);
767 bm.lockPixels();
768 if (bm.getPixels()) {
769 return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
770 }
771 return false;
772 }
773
writePixels(const SkImageInfo & origInfo,const void * pixels,size_t rowBytes,int x,int y)774 bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
775 int x, int y) {
776 switch (origInfo.colorType()) {
777 case kUnknown_SkColorType:
778 case kIndex_8_SkColorType:
779 return false;
780 default:
781 break;
782 }
783 if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
784 return false;
785 }
786
787 const SkISize size = this->getBaseLayerSize();
788 SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
789 if (!target.intersect(0, 0, size.width(), size.height())) {
790 return false;
791 }
792
793 SkBaseDevice* device = this->getDevice();
794 if (!device) {
795 return false;
796 }
797
798 // the intersect may have shrunk info's logical size
799 const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
800
801 // if x or y are negative, then we have to adjust pixels
802 if (x > 0) {
803 x = 0;
804 }
805 if (y > 0) {
806 y = 0;
807 }
808 // here x,y are either 0 or negative
809 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
810
811 // Tell our owning surface to bump its generation ID
812 this->predrawNotify();
813
814 // The device can assert that the requested area is always contained in its bounds
815 return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
816 }
817
canvasForDrawIter()818 SkCanvas* SkCanvas::canvasForDrawIter() {
819 return this;
820 }
821
822 //////////////////////////////////////////////////////////////////////////////
823
updateDeviceCMCache()824 void SkCanvas::updateDeviceCMCache() {
825 if (fDeviceCMDirty) {
826 const SkMatrix& totalMatrix = this->getTotalMatrix();
827 const SkRasterClip& totalClip = fMCRec->fRasterClip;
828 DeviceCM* layer = fMCRec->fTopLayer;
829
830 if (NULL == layer->fNext) { // only one layer
831 layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL);
832 } else {
833 SkRasterClip clip(totalClip);
834 do {
835 layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
836 } while ((layer = layer->fNext) != NULL);
837 }
838 fDeviceCMDirty = false;
839 }
840 }
841
842 ///////////////////////////////////////////////////////////////////////////////
843
checkForDeferredSave()844 void SkCanvas::checkForDeferredSave() {
845 if (fMCRec->fDeferredSaveCount > 0) {
846 this->doSave();
847 }
848 }
849
getSaveCount() const850 int SkCanvas::getSaveCount() const {
851 #ifdef SK_DEBUG
852 int count = 0;
853 SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
854 for (;;) {
855 const MCRec* rec = (const MCRec*)iter.next();
856 if (!rec) {
857 break;
858 }
859 count += 1 + rec->fDeferredSaveCount;
860 }
861 SkASSERT(count == fSaveCount);
862 #endif
863 return fSaveCount;
864 }
865
save()866 int SkCanvas::save() {
867 fSaveCount += 1;
868 fMCRec->fDeferredSaveCount += 1;
869 return this->getSaveCount() - 1; // return our prev value
870 }
871
doSave()872 void SkCanvas::doSave() {
873 this->willSave();
874
875 SkASSERT(fMCRec->fDeferredSaveCount > 0);
876 fMCRec->fDeferredSaveCount -= 1;
877 this->internalSave();
878 }
879
restore()880 void SkCanvas::restore() {
881 if (fMCRec->fDeferredSaveCount > 0) {
882 SkASSERT(fSaveCount > 1);
883 fSaveCount -= 1;
884 fMCRec->fDeferredSaveCount -= 1;
885 } else {
886 // check for underflow
887 if (fMCStack.count() > 1) {
888 this->willRestore();
889 SkASSERT(fSaveCount > 1);
890 fSaveCount -= 1;
891 this->internalRestore();
892 this->didRestore();
893 }
894 }
895 }
896
restoreToCount(int count)897 void SkCanvas::restoreToCount(int count) {
898 // sanity check
899 if (count < 1) {
900 count = 1;
901 }
902
903 int n = this->getSaveCount() - count;
904 for (int i = 0; i < n; ++i) {
905 this->restore();
906 }
907 }
908
internalSave()909 void SkCanvas::internalSave() {
910 MCRec* newTop = (MCRec*)fMCStack.push_back();
911 new (newTop) MCRec(*fMCRec); // balanced in restore()
912 fMCRec = newTop;
913
914 fClipStack->save();
915 }
916
bounds_affects_clip(SkCanvas::SaveFlags flags)917 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
918 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
919 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
920 #else
921 return true;
922 #endif
923 }
924
clipRectBounds(const SkRect * bounds,SaveFlags flags,SkIRect * intersection,const SkImageFilter * imageFilter)925 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
926 SkIRect* intersection, const SkImageFilter* imageFilter) {
927 SkIRect clipBounds;
928 if (!this->getClipDeviceBounds(&clipBounds)) {
929 return false;
930 }
931
932 const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix()
933
934 if (imageFilter) {
935 imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
936 }
937 SkIRect ir;
938 if (bounds) {
939 SkRect r;
940
941 ctm.mapRect(&r, *bounds);
942 r.roundOut(&ir);
943 // early exit if the layer's bounds are clipped out
944 if (!ir.intersect(clipBounds)) {
945 if (bounds_affects_clip(flags)) {
946 fCachedLocalClipBoundsDirty = true;
947 fMCRec->fRasterClip.setEmpty();
948 }
949 return false;
950 }
951 } else { // no user bounds, so just use the clip
952 ir = clipBounds;
953 }
954 SkASSERT(!ir.isEmpty());
955
956 if (bounds_affects_clip(flags)) {
957 // Simplify the current clips since they will be applied properly during restore()
958 fCachedLocalClipBoundsDirty = true;
959 fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
960 fMCRec->fRasterClip.setRect(ir);
961 }
962
963 if (intersection) {
964 *intersection = ir;
965 }
966 return true;
967 }
968
saveLayer(const SkRect * bounds,const SkPaint * paint)969 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
970 if (gIgnoreSaveLayerBounds) {
971 bounds = NULL;
972 }
973 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
974 fSaveCount += 1;
975 this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
976 return this->getSaveCount() - 1;
977 }
978
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)979 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
980 if (gIgnoreSaveLayerBounds) {
981 bounds = NULL;
982 }
983 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
984 fSaveCount += 1;
985 this->internalSaveLayer(bounds, paint, flags, strategy);
986 return this->getSaveCount() - 1;
987 }
988
internalSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags,SaveLayerStrategy strategy)989 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
990 SaveLayerStrategy strategy) {
991 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
992 flags |= kClipToLayer_SaveFlag;
993 #endif
994
995 // do this before we create the layer. We don't call the public save() since
996 // that would invoke a possibly overridden virtual
997 this->internalSave();
998
999 fDeviceCMDirty = true;
1000
1001 SkIRect ir;
1002 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
1003 return;
1004 }
1005
1006 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1007 // the clipRectBounds() call above?
1008 if (kNoLayer_SaveLayerStrategy == strategy) {
1009 return;
1010 }
1011
1012 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
1013 SkPixelGeometry geo = fProps.pixelGeometry();
1014 if (paint) {
1015 // TODO: perhaps add a query to filters so we might preserve opaqueness...
1016 if (paint->getImageFilter() || paint->getColorFilter()) {
1017 isOpaque = false;
1018 geo = kUnknown_SkPixelGeometry;
1019 }
1020 }
1021 SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
1022 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
1023
1024 SkBaseDevice* device = this->getTopDevice();
1025 if (NULL == device) {
1026 SkDebugf("Unable to find device for layer.");
1027 return;
1028 }
1029
1030 bool forceSpriteOnRestore = false;
1031 {
1032 const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
1033 const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
1034 SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
1035 if (NULL == newDev) {
1036 // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
1037 newDev = SkBitmapDevice::Create(createInfo.fInfo);
1038 if (NULL == newDev) {
1039 SkErrorInternals::SetError(kInternalError_SkError,
1040 "Unable to create device for layer.");
1041 return;
1042 }
1043 forceSpriteOnRestore = true;
1044 }
1045 device = newDev;
1046 }
1047
1048 device->setOrigin(ir.fLeft, ir.fTop);
1049 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip,
1050 forceSpriteOnRestore));
1051 device->unref();
1052
1053 layer->fNext = fMCRec->fTopLayer;
1054 fMCRec->fLayer = layer;
1055 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
1056 }
1057
saveLayerAlpha(const SkRect * bounds,U8CPU alpha)1058 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1059 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1060 }
1061
saveLayerAlpha(const SkRect * bounds,U8CPU alpha,SaveFlags flags)1062 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
1063 SaveFlags flags) {
1064 if (0xFF == alpha) {
1065 return this->saveLayer(bounds, NULL, flags);
1066 } else {
1067 SkPaint tmpPaint;
1068 tmpPaint.setAlpha(alpha);
1069 return this->saveLayer(bounds, &tmpPaint, flags);
1070 }
1071 }
1072
internalRestore()1073 void SkCanvas::internalRestore() {
1074 SkASSERT(fMCStack.count() != 0);
1075
1076 fDeviceCMDirty = true;
1077 fCachedLocalClipBoundsDirty = true;
1078
1079 fClipStack->restore();
1080
1081 // reserve our layer (if any)
1082 DeviceCM* layer = fMCRec->fLayer; // may be null
1083 // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1084 fMCRec->fLayer = NULL;
1085
1086 // now do the normal restore()
1087 fMCRec->~MCRec(); // balanced in save()
1088 fMCStack.pop_back();
1089 fMCRec = (MCRec*)fMCStack.back();
1090
1091 /* Time to draw the layer's offscreen. We can't call the public drawSprite,
1092 since if we're being recorded, we don't want to record this (the
1093 recorder will have already recorded the restore).
1094 */
1095 if (layer) {
1096 if (layer->fNext) {
1097 const SkIPoint& origin = layer->fDevice->getOrigin();
1098 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1099 layer->fPaint, layer->fDeviceIsBitmapDevice);
1100 // reset this, since internalDrawDevice will have set it to true
1101 fDeviceCMDirty = true;
1102 SkDELETE(layer);
1103 } else {
1104 // we're at the root
1105 SkASSERT(layer == (void*)fDeviceCMStorage);
1106 layer->~DeviceCM();
1107 }
1108 }
1109 }
1110
newSurface(const SkImageInfo & info,const SkSurfaceProps * props)1111 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1112 if (NULL == props) {
1113 props = &fProps;
1114 }
1115 return this->onNewSurface(info, *props);
1116 }
1117
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)1118 SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1119 SkBaseDevice* dev = this->getDevice();
1120 return dev ? dev->newSurface(info, props) : NULL;
1121 }
1122
imageInfo() const1123 SkImageInfo SkCanvas::imageInfo() const {
1124 SkBaseDevice* dev = this->getDevice();
1125 if (dev) {
1126 return dev->imageInfo();
1127 } else {
1128 return SkImageInfo::MakeUnknown(0, 0);
1129 }
1130 }
1131
peekPixels(SkImageInfo * info,size_t * rowBytes)1132 const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1133 return this->onPeekPixels(info, rowBytes);
1134 }
1135
onPeekPixels(SkImageInfo * info,size_t * rowBytes)1136 const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1137 SkBaseDevice* dev = this->getDevice();
1138 return dev ? dev->peekPixels(info, rowBytes) : NULL;
1139 }
1140
accessTopLayerPixels(SkImageInfo * info,size_t * rowBytes,SkIPoint * origin)1141 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1142 void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
1143 if (pixels && origin) {
1144 *origin = this->getTopDevice(false)->getOrigin();
1145 }
1146 return pixels;
1147 }
1148
onAccessTopLayerPixels(SkImageInfo * info,size_t * rowBytes)1149 void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
1150 SkBaseDevice* dev = this->getTopDevice();
1151 return dev ? dev->accessPixels(info, rowBytes) : NULL;
1152 }
1153
SkAutoROCanvasPixels(SkCanvas * canvas)1154 SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1155 fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1156 if (NULL == fAddr) {
1157 fInfo = canvas->imageInfo();
1158 if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1159 return; // failure, fAddr is NULL
1160 }
1161 if (!canvas->readPixels(&fBitmap, 0, 0)) {
1162 return; // failure, fAddr is NULL
1163 }
1164 fAddr = fBitmap.getPixels();
1165 fRowBytes = fBitmap.rowBytes();
1166 }
1167 SkASSERT(fAddr); // success
1168 }
1169
asROBitmap(SkBitmap * bitmap) const1170 bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1171 if (fAddr) {
1172 return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1173 } else {
1174 bitmap->reset();
1175 return false;
1176 }
1177 }
1178
1179 /////////////////////////////////////////////////////////////////////////////
internalDrawBitmap(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)1180 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
1181 const SkMatrix& matrix, const SkPaint* paint) {
1182 if (bitmap.drawsNothing()) {
1183 return;
1184 }
1185
1186 SkLazyPaint lazy;
1187 if (NULL == paint) {
1188 paint = lazy.init();
1189 }
1190
1191 SkDEBUGCODE(bitmap.validate();)
1192
1193 SkRect storage;
1194 const SkRect* bounds = NULL;
1195 if (paint && paint->canComputeFastBounds()) {
1196 bitmap.getBounds(&storage);
1197 matrix.mapRect(&storage);
1198 bounds = &paint->computeFastBounds(storage, &storage);
1199 }
1200
1201 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
1202
1203 while (iter.next()) {
1204 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
1205 }
1206
1207 LOOPER_END
1208 }
1209
internalDrawDevice(SkBaseDevice * srcDev,int x,int y,const SkPaint * paint,bool deviceIsBitmapDevice)1210 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1211 const SkPaint* paint, bool deviceIsBitmapDevice) {
1212 SkPaint tmp;
1213 if (NULL == paint) {
1214 paint = &tmp;
1215 }
1216
1217 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1218 while (iter.next()) {
1219 SkBaseDevice* dstDev = iter.fDevice;
1220 paint = &looper.paint();
1221 SkImageFilter* filter = paint->getImageFilter();
1222 SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1223 if (filter && !dstDev->canHandleImageFilter(filter)) {
1224 SkDeviceImageFilterProxy proxy(dstDev, fProps);
1225 SkBitmap dst;
1226 SkIPoint offset = SkIPoint::Make(0, 0);
1227 const SkBitmap& src = srcDev->accessBitmap(false);
1228 SkMatrix matrix = *iter.fMatrix;
1229 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1230 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1231 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
1232 SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1233 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1234 SkPaint tmpUnfiltered(*paint);
1235 tmpUnfiltered.setImageFilter(NULL);
1236 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1237 tmpUnfiltered);
1238 }
1239 } else if (deviceIsBitmapDevice) {
1240 const SkBitmap& src = srcDev->accessBitmap(false);
1241 dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
1242 } else {
1243 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1244 }
1245 }
1246 LOOPER_END
1247 }
1248
onDrawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint * paint)1249 void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
1250 if (gTreatSpriteAsBitmap) {
1251 this->save();
1252 this->resetMatrix();
1253 this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
1254 this->restore();
1255 return;
1256 }
1257
1258 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
1259 if (bitmap.drawsNothing()) {
1260 return;
1261 }
1262 SkDEBUGCODE(bitmap.validate();)
1263
1264 SkPaint tmp;
1265 if (NULL == paint) {
1266 paint = &tmp;
1267 }
1268
1269 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1270
1271 while (iter.next()) {
1272 paint = &looper.paint();
1273 SkImageFilter* filter = paint->getImageFilter();
1274 SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1275 if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1276 SkDeviceImageFilterProxy proxy(iter.fDevice, fProps);
1277 SkBitmap dst;
1278 SkIPoint offset = SkIPoint::Make(0, 0);
1279 SkMatrix matrix = *iter.fMatrix;
1280 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1281 const SkIRect clipBounds = bitmap.bounds();
1282 SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
1283 SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1284 if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
1285 SkPaint tmpUnfiltered(*paint);
1286 tmpUnfiltered.setImageFilter(NULL);
1287 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1288 tmpUnfiltered);
1289 }
1290 } else {
1291 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1292 }
1293 }
1294 LOOPER_END
1295 }
1296
1297 /////////////////////////////////////////////////////////////////////////////
translate(SkScalar dx,SkScalar dy)1298 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1299 SkMatrix m;
1300 m.setTranslate(dx, dy);
1301 this->concat(m);
1302 }
1303
scale(SkScalar sx,SkScalar sy)1304 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1305 SkMatrix m;
1306 m.setScale(sx, sy);
1307 this->concat(m);
1308 }
1309
rotate(SkScalar degrees)1310 void SkCanvas::rotate(SkScalar degrees) {
1311 SkMatrix m;
1312 m.setRotate(degrees);
1313 this->concat(m);
1314 }
1315
skew(SkScalar sx,SkScalar sy)1316 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1317 SkMatrix m;
1318 m.setSkew(sx, sy);
1319 this->concat(m);
1320 }
1321
concat(const SkMatrix & matrix)1322 void SkCanvas::concat(const SkMatrix& matrix) {
1323 if (matrix.isIdentity()) {
1324 return;
1325 }
1326
1327 this->checkForDeferredSave();
1328 fDeviceCMDirty = true;
1329 fCachedLocalClipBoundsDirty = true;
1330 fMCRec->fMatrix.preConcat(matrix);
1331
1332 this->didConcat(matrix);
1333 }
1334
setMatrix(const SkMatrix & matrix)1335 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1336 this->checkForDeferredSave();
1337 fDeviceCMDirty = true;
1338 fCachedLocalClipBoundsDirty = true;
1339 fMCRec->fMatrix = matrix;
1340 this->didSetMatrix(matrix);
1341 }
1342
resetMatrix()1343 void SkCanvas::resetMatrix() {
1344 SkMatrix matrix;
1345
1346 matrix.reset();
1347 this->setMatrix(matrix);
1348 }
1349
1350 //////////////////////////////////////////////////////////////////////////////
1351
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)1352 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1353 this->checkForDeferredSave();
1354 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1355 this->onClipRect(rect, op, edgeStyle);
1356 }
1357
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle edgeStyle)1358 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1359 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1360 if (SkRegion::kIntersect_Op == op) {
1361 if (fMCRec->fRasterClip.isEmpty()) {
1362 return false;
1363 }
1364
1365 if (this->quickReject(rect)) {
1366 fDeviceCMDirty = true;
1367 fCachedLocalClipBoundsDirty = true;
1368
1369 fClipStack->clipEmpty();
1370 return fMCRec->fRasterClip.setEmpty();
1371 }
1372 }
1373 #endif
1374
1375 AutoValidateClip avc(this);
1376
1377 fDeviceCMDirty = true;
1378 fCachedLocalClipBoundsDirty = true;
1379 if (!fAllowSoftClip) {
1380 edgeStyle = kHard_ClipEdgeStyle;
1381 }
1382
1383 if (fMCRec->fMatrix.rectStaysRect()) {
1384 // for these simpler matrices, we can stay a rect even after applying
1385 // the matrix. This means we don't have to a) make a path, and b) tell
1386 // the region code to scan-convert the path, only to discover that it
1387 // is really just a rect.
1388 SkRect r;
1389
1390 fMCRec->fMatrix.mapRect(&r, rect);
1391 fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1392 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
1393 } else {
1394 // since we're rotated or some such thing, we convert the rect to a path
1395 // and clip against that, since it can handle any matrix. However, to
1396 // avoid recursion in the case where we are subclassed (e.g. Pictures)
1397 // we explicitly call "our" version of clipPath.
1398 SkPath path;
1399
1400 path.addRect(rect);
1401 this->SkCanvas::onClipPath(path, op, edgeStyle);
1402 }
1403 }
1404
rasterclip_path(SkRasterClip * rc,const SkCanvas * canvas,const SkPath & devPath,SkRegion::Op op,bool doAA)1405 static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
1406 SkRegion::Op op, bool doAA) {
1407 rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1408 }
1409
clipRRect(const SkRRect & rrect,SkRegion::Op op,bool doAA)1410 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1411 this->checkForDeferredSave();
1412 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1413 if (rrect.isRect()) {
1414 this->onClipRect(rrect.getBounds(), op, edgeStyle);
1415 } else {
1416 this->onClipRRect(rrect, op, edgeStyle);
1417 }
1418 }
1419
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle edgeStyle)1420 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1421 SkRRect transformedRRect;
1422 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1423 AutoValidateClip avc(this);
1424
1425 fDeviceCMDirty = true;
1426 fCachedLocalClipBoundsDirty = true;
1427 if (!fAllowSoftClip) {
1428 edgeStyle = kHard_ClipEdgeStyle;
1429 }
1430
1431 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1432
1433 SkPath devPath;
1434 devPath.addRRect(transformedRRect);
1435
1436 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1437 return;
1438 }
1439
1440 SkPath path;
1441 path.addRRect(rrect);
1442 // call the non-virtual version
1443 this->SkCanvas::onClipPath(path, op, edgeStyle);
1444 }
1445
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)1446 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1447 this->checkForDeferredSave();
1448 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1449 SkRect r;
1450 if (!path.isInverseFillType() && path.isRect(&r)) {
1451 this->onClipRect(r, op, edgeStyle);
1452 } else {
1453 this->onClipPath(path, op, edgeStyle);
1454 }
1455 }
1456
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle edgeStyle)1457 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1458 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1459 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1460 if (fMCRec->fRasterClip.isEmpty()) {
1461 return false;
1462 }
1463
1464 if (this->quickReject(path.getBounds())) {
1465 fDeviceCMDirty = true;
1466 fCachedLocalClipBoundsDirty = true;
1467
1468 fClipStack->clipEmpty();
1469 return fMCRec->fRasterClip.setEmpty();
1470 }
1471 }
1472 #endif
1473
1474 AutoValidateClip avc(this);
1475
1476 fDeviceCMDirty = true;
1477 fCachedLocalClipBoundsDirty = true;
1478 if (!fAllowSoftClip) {
1479 edgeStyle = kHard_ClipEdgeStyle;
1480 }
1481
1482 SkPath devPath;
1483 path.transform(fMCRec->fMatrix, &devPath);
1484
1485 // Check if the transfomation, or the original path itself
1486 // made us empty. Note this can also happen if we contained NaN
1487 // values. computing the bounds detects this, and will set our
1488 // bounds to empty if that is the case. (see SkRect::set(pts, count))
1489 if (devPath.getBounds().isEmpty()) {
1490 // resetting the path will remove any NaN or other wanky values
1491 // that might upset our scan converter.
1492 devPath.reset();
1493 }
1494
1495 // if we called path.swap() we could avoid a deep copy of this path
1496 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1497
1498 if (fAllowSimplifyClip) {
1499 bool clipIsAA = getClipStack()->asPath(&devPath);
1500 if (clipIsAA) {
1501 edgeStyle = kSoft_ClipEdgeStyle;
1502 }
1503
1504 op = SkRegion::kReplace_Op;
1505 }
1506
1507 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
1508 }
1509
clipRegion(const SkRegion & rgn,SkRegion::Op op)1510 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1511 this->checkForDeferredSave();
1512 this->onClipRegion(rgn, op);
1513 }
1514
onClipRegion(const SkRegion & rgn,SkRegion::Op op)1515 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1516 AutoValidateClip avc(this);
1517
1518 fDeviceCMDirty = true;
1519 fCachedLocalClipBoundsDirty = true;
1520
1521 // todo: signal fClipStack that we have a region, and therefore (I guess)
1522 // we have to ignore it, and use the region directly?
1523 fClipStack->clipDevRect(rgn.getBounds(), op);
1524
1525 fMCRec->fRasterClip.op(rgn, op);
1526 }
1527
1528 #ifdef SK_DEBUG
validateClip() const1529 void SkCanvas::validateClip() const {
1530 // construct clipRgn from the clipstack
1531 const SkBaseDevice* device = this->getDevice();
1532 if (!device) {
1533 SkASSERT(this->isClipEmpty());
1534 return;
1535 }
1536
1537 SkIRect ir;
1538 ir.set(0, 0, device->width(), device->height());
1539 SkRasterClip tmpClip(ir, fConservativeRasterClip);
1540
1541 SkClipStack::B2TIter iter(*fClipStack);
1542 const SkClipStack::Element* element;
1543 while ((element = iter.next()) != NULL) {
1544 switch (element->getType()) {
1545 case SkClipStack::Element::kRect_Type:
1546 element->getRect().round(&ir);
1547 tmpClip.op(ir, element->getOp());
1548 break;
1549 case SkClipStack::Element::kEmpty_Type:
1550 tmpClip.setEmpty();
1551 break;
1552 default: {
1553 SkPath path;
1554 element->asPath(&path);
1555 rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
1556 break;
1557 }
1558 }
1559 }
1560 }
1561 #endif
1562
replayClips(ClipVisitor * visitor) const1563 void SkCanvas::replayClips(ClipVisitor* visitor) const {
1564 SkClipStack::B2TIter iter(*fClipStack);
1565 const SkClipStack::Element* element;
1566
1567 while ((element = iter.next()) != NULL) {
1568 element->replay(visitor);
1569 }
1570 }
1571
1572 ///////////////////////////////////////////////////////////////////////////////
1573
isClipEmpty() const1574 bool SkCanvas::isClipEmpty() const {
1575 return fMCRec->fRasterClip.isEmpty();
1576 }
1577
isClipRect() const1578 bool SkCanvas::isClipRect() const {
1579 return fMCRec->fRasterClip.isRect();
1580 }
1581
quickReject(const SkRect & rect) const1582 bool SkCanvas::quickReject(const SkRect& rect) const {
1583 if (!rect.isFinite())
1584 return true;
1585
1586 if (fMCRec->fRasterClip.isEmpty()) {
1587 return true;
1588 }
1589
1590 if (fMCRec->fMatrix.hasPerspective()) {
1591 SkRect dst;
1592 fMCRec->fMatrix.mapRect(&dst, rect);
1593 return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1594 } else {
1595 const SkRect& clipR = this->getLocalClipBounds();
1596
1597 // for speed, do the most likely reject compares first
1598 // TODO: should we use | instead, or compare all 4 at once?
1599 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1600 return true;
1601 }
1602 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1603 return true;
1604 }
1605 return false;
1606 }
1607 }
1608
quickReject(const SkPath & path) const1609 bool SkCanvas::quickReject(const SkPath& path) const {
1610 return path.isEmpty() || this->quickReject(path.getBounds());
1611 }
1612
getClipBounds(SkRect * bounds) const1613 bool SkCanvas::getClipBounds(SkRect* bounds) const {
1614 SkIRect ibounds;
1615 if (!this->getClipDeviceBounds(&ibounds)) {
1616 return false;
1617 }
1618
1619 SkMatrix inverse;
1620 // if we can't invert the CTM, we can't return local clip bounds
1621 if (!fMCRec->fMatrix.invert(&inverse)) {
1622 if (bounds) {
1623 bounds->setEmpty();
1624 }
1625 return false;
1626 }
1627
1628 if (bounds) {
1629 SkRect r;
1630 // adjust it outwards in case we are antialiasing
1631 const int inset = 1;
1632
1633 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1634 ibounds.fRight + inset, ibounds.fBottom + inset);
1635 inverse.mapRect(bounds, r);
1636 }
1637 return true;
1638 }
1639
getClipDeviceBounds(SkIRect * bounds) const1640 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1641 const SkRasterClip& clip = fMCRec->fRasterClip;
1642 if (clip.isEmpty()) {
1643 if (bounds) {
1644 bounds->setEmpty();
1645 }
1646 return false;
1647 }
1648
1649 if (bounds) {
1650 *bounds = clip.getBounds();
1651 }
1652 return true;
1653 }
1654
getTotalMatrix() const1655 const SkMatrix& SkCanvas::getTotalMatrix() const {
1656 return fMCRec->fMatrix;
1657 }
1658
internal_private_getTotalClip() const1659 const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1660 return fMCRec->fRasterClip.forceGetBW();
1661 }
1662
internal_private_accessTopLayerRenderTarget()1663 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1664 SkBaseDevice* dev = this->getTopDevice();
1665 return dev ? dev->accessRenderTarget() : NULL;
1666 }
1667
getGrContext()1668 GrContext* SkCanvas::getGrContext() {
1669 #if SK_SUPPORT_GPU
1670 SkBaseDevice* device = this->getTopDevice();
1671 if (device) {
1672 GrRenderTarget* renderTarget = device->accessRenderTarget();
1673 if (renderTarget) {
1674 return renderTarget->getContext();
1675 }
1676 }
1677 #endif
1678
1679 return NULL;
1680
1681 }
1682
drawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1683 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1684 const SkPaint& paint) {
1685 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1686 if (outer.isEmpty()) {
1687 return;
1688 }
1689 if (inner.isEmpty()) {
1690 this->drawRRect(outer, paint);
1691 return;
1692 }
1693
1694 // We don't have this method (yet), but technically this is what we should
1695 // be able to assert...
1696 // SkASSERT(outer.contains(inner));
1697 //
1698 // For now at least check for containment of bounds
1699 SkASSERT(outer.getBounds().contains(inner.getBounds()));
1700
1701 this->onDrawDRRect(outer, inner, paint);
1702 }
1703
1704 // These need to stop being virtual -- clients need to override the onDraw... versions
1705
drawPaint(const SkPaint & paint)1706 void SkCanvas::drawPaint(const SkPaint& paint) {
1707 this->onDrawPaint(paint);
1708 }
1709
drawRect(const SkRect & r,const SkPaint & paint)1710 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1711 this->onDrawRect(r, paint);
1712 }
1713
drawOval(const SkRect & r,const SkPaint & paint)1714 void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1715 this->onDrawOval(r, paint);
1716 }
1717
drawRRect(const SkRRect & rrect,const SkPaint & paint)1718 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1719 this->onDrawRRect(rrect, paint);
1720 }
1721
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1722 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1723 this->onDrawPoints(mode, count, pts, paint);
1724 }
1725
drawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)1726 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
1727 const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
1728 const uint16_t indices[], int indexCount, const SkPaint& paint) {
1729 this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
1730 indices, indexCount, paint);
1731 }
1732
drawPath(const SkPath & path,const SkPaint & paint)1733 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1734 this->onDrawPath(path, paint);
1735 }
1736
drawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)1737 void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1738 this->onDrawImage(image, x, y, paint);
1739 }
1740
drawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint)1741 void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1742 const SkPaint* paint) {
1743 if (dst.isEmpty()) {
1744 return;
1745 }
1746 this->onDrawImageRect(image, src, dst, paint);
1747 }
1748
drawBitmap(const SkBitmap & bitmap,SkScalar dx,SkScalar dy,const SkPaint * paint)1749 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1750 if (bitmap.empty()) {
1751 return;
1752 }
1753 this->onDrawBitmap(bitmap, dx, dy, paint);
1754 }
1755
drawBitmapRectToRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)1756 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1757 const SkPaint* paint, DrawBitmapRectFlags flags) {
1758 if (bitmap.empty()) {
1759 return;
1760 }
1761 this->onDrawBitmapRect(bitmap, src, dst, paint, flags);
1762 }
1763
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1764 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1765 const SkPaint* paint) {
1766 if (bitmap.empty()) {
1767 return;
1768 }
1769 this->onDrawBitmapNine(bitmap, center, dst, paint);
1770 }
1771
drawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint)1772 void SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
1773 if (bitmap.empty()) {
1774 return;
1775 }
1776 this->onDrawSprite(bitmap, left, top, paint);
1777 }
1778
1779 //////////////////////////////////////////////////////////////////////////////
1780 // These are the virtual drawing methods
1781 //////////////////////////////////////////////////////////////////////////////
1782
onDiscard()1783 void SkCanvas::onDiscard() {
1784 if (fSurfaceBase) {
1785 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1786 }
1787 }
1788
onDrawPaint(const SkPaint & paint)1789 void SkCanvas::onDrawPaint(const SkPaint& paint) {
1790 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1791 this->internalDrawPaint(paint);
1792 }
1793
internalDrawPaint(const SkPaint & paint)1794 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1795 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
1796
1797 while (iter.next()) {
1798 iter.fDevice->drawPaint(iter, looper.paint());
1799 }
1800
1801 LOOPER_END
1802 }
1803
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1804 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
1805 const SkPaint& paint) {
1806 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
1807 if ((long)count <= 0) {
1808 return;
1809 }
1810
1811 SkRect r, storage;
1812 const SkRect* bounds = NULL;
1813 if (paint.canComputeFastBounds()) {
1814 // special-case 2 points (common for drawing a single line)
1815 if (2 == count) {
1816 r.set(pts[0], pts[1]);
1817 } else {
1818 r.set(pts, SkToInt(count));
1819 }
1820 bounds = &paint.computeFastStrokeBounds(r, &storage);
1821 if (this->quickReject(*bounds)) {
1822 return;
1823 }
1824 }
1825
1826 SkASSERT(pts != NULL);
1827
1828 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
1829
1830 while (iter.next()) {
1831 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1832 }
1833
1834 LOOPER_END
1835 }
1836
onDrawRect(const SkRect & r,const SkPaint & paint)1837 void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
1838 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
1839 SkRect storage;
1840 const SkRect* bounds = NULL;
1841 if (paint.canComputeFastBounds()) {
1842 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
1843 // To prevent accidental rejecting at this stage, we have to sort it before we check.
1844 SkRect tmp(r);
1845 tmp.sort();
1846
1847 bounds = &paint.computeFastBounds(tmp, &storage);
1848 if (this->quickReject(*bounds)) {
1849 return;
1850 }
1851 }
1852
1853 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
1854
1855 while (iter.next()) {
1856 iter.fDevice->drawRect(iter, r, looper.paint());
1857 }
1858
1859 LOOPER_END
1860 }
1861
onDrawOval(const SkRect & oval,const SkPaint & paint)1862 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
1863 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
1864 SkRect storage;
1865 const SkRect* bounds = NULL;
1866 if (paint.canComputeFastBounds()) {
1867 bounds = &paint.computeFastBounds(oval, &storage);
1868 if (this->quickReject(*bounds)) {
1869 return;
1870 }
1871 }
1872
1873 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
1874
1875 while (iter.next()) {
1876 iter.fDevice->drawOval(iter, oval, looper.paint());
1877 }
1878
1879 LOOPER_END
1880 }
1881
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)1882 void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
1883 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
1884 SkRect storage;
1885 const SkRect* bounds = NULL;
1886 if (paint.canComputeFastBounds()) {
1887 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
1888 if (this->quickReject(*bounds)) {
1889 return;
1890 }
1891 }
1892
1893 if (rrect.isRect()) {
1894 // call the non-virtual version
1895 this->SkCanvas::drawRect(rrect.getBounds(), paint);
1896 return;
1897 } else if (rrect.isOval()) {
1898 // call the non-virtual version
1899 this->SkCanvas::drawOval(rrect.getBounds(), paint);
1900 return;
1901 }
1902
1903 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1904
1905 while (iter.next()) {
1906 iter.fDevice->drawRRect(iter, rrect, looper.paint());
1907 }
1908
1909 LOOPER_END
1910 }
1911
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1912 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1913 const SkPaint& paint) {
1914 SkRect storage;
1915 const SkRect* bounds = NULL;
1916 if (paint.canComputeFastBounds()) {
1917 bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1918 if (this->quickReject(*bounds)) {
1919 return;
1920 }
1921 }
1922
1923 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1924
1925 while (iter.next()) {
1926 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1927 }
1928
1929 LOOPER_END
1930 }
1931
onDrawPath(const SkPath & path,const SkPaint & paint)1932 void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
1933 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
1934 if (!path.isFinite()) {
1935 return;
1936 }
1937
1938 SkRect storage;
1939 const SkRect* bounds = NULL;
1940 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1941 const SkRect& pathBounds = path.getBounds();
1942 bounds = &paint.computeFastBounds(pathBounds, &storage);
1943 if (this->quickReject(*bounds)) {
1944 return;
1945 }
1946 }
1947
1948 const SkRect& r = path.getBounds();
1949 if (r.width() <= 0 && r.height() <= 0) {
1950 if (path.isInverseFillType()) {
1951 this->internalDrawPaint(paint);
1952 }
1953 return;
1954 }
1955
1956 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
1957
1958 while (iter.next()) {
1959 iter.fDevice->drawPath(iter, path, looper.paint());
1960 }
1961
1962 LOOPER_END
1963 }
1964
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)1965 void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1966 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
1967 SkRect bounds = SkRect::MakeXYWH(x, y,
1968 SkIntToScalar(image->width()), SkIntToScalar(image->height()));
1969 if (NULL == paint || paint->canComputeFastBounds()) {
1970 if (paint) {
1971 paint->computeFastBounds(bounds, &bounds);
1972 }
1973 if (this->quickReject(bounds)) {
1974 return;
1975 }
1976 }
1977
1978 SkLazyPaint lazy;
1979 if (NULL == paint) {
1980 paint = lazy.init();
1981 }
1982
1983 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
1984
1985 while (iter.next()) {
1986 iter.fDevice->drawImage(iter, image, x, y, looper.paint());
1987 }
1988
1989 LOOPER_END
1990 }
1991
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint)1992 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1993 const SkPaint* paint) {
1994 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
1995 SkRect storage;
1996 const SkRect* bounds = &dst;
1997 if (NULL == paint || paint->canComputeFastBounds()) {
1998 if (paint) {
1999 bounds = &paint->computeFastBounds(dst, &storage);
2000 }
2001 if (this->quickReject(*bounds)) {
2002 return;
2003 }
2004 }
2005 SkLazyPaint lazy;
2006 if (NULL == paint) {
2007 paint = lazy.init();
2008 }
2009
2010 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
2011
2012 while (iter.next()) {
2013 iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint());
2014 }
2015
2016 LOOPER_END
2017 }
2018
onDrawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)2019 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2020 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
2021 SkDEBUGCODE(bitmap.validate();)
2022
2023 if (NULL == paint || paint->canComputeFastBounds()) {
2024 SkRect bounds = {
2025 x, y,
2026 x + SkIntToScalar(bitmap.width()),
2027 y + SkIntToScalar(bitmap.height())
2028 };
2029 if (paint) {
2030 (void)paint->computeFastBounds(bounds, &bounds);
2031 }
2032 if (this->quickReject(bounds)) {
2033 return;
2034 }
2035 }
2036
2037 SkMatrix matrix;
2038 matrix.setTranslate(x, y);
2039 this->internalDrawBitmap(bitmap, matrix, paint);
2040 }
2041
2042 // this one is non-virtual, so it can be called safely by other canvas apis
internalDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)2043 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2044 const SkRect& dst, const SkPaint* paint,
2045 DrawBitmapRectFlags flags) {
2046 if (bitmap.drawsNothing() || dst.isEmpty()) {
2047 return;
2048 }
2049
2050 SkRect storage;
2051 const SkRect* bounds = &dst;
2052 if (NULL == paint || paint->canComputeFastBounds()) {
2053 if (paint) {
2054 bounds = &paint->computeFastBounds(dst, &storage);
2055 }
2056 if (this->quickReject(*bounds)) {
2057 return;
2058 }
2059 }
2060
2061 SkLazyPaint lazy;
2062 if (NULL == paint) {
2063 paint = lazy.init();
2064 }
2065
2066 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
2067
2068 while (iter.next()) {
2069 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2070 }
2071
2072 LOOPER_END
2073 }
2074
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)2075 void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2076 const SkPaint* paint, DrawBitmapRectFlags flags) {
2077 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
2078 SkDEBUGCODE(bitmap.validate();)
2079 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
2080 }
2081
internalDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2082 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
2083 const SkIRect& center, const SkRect& dst,
2084 const SkPaint* paint) {
2085 if (bitmap.drawsNothing()) {
2086 return;
2087 }
2088 if (NULL == paint || paint->canComputeFastBounds()) {
2089 SkRect storage;
2090 const SkRect* bounds = &dst;
2091 if (paint) {
2092 bounds = &paint->computeFastBounds(dst, &storage);
2093 }
2094 if (this->quickReject(*bounds)) {
2095 return;
2096 }
2097 }
2098
2099 const int32_t w = bitmap.width();
2100 const int32_t h = bitmap.height();
2101
2102 SkIRect c = center;
2103 // pin center to the bounds of the bitmap
2104 c.fLeft = SkMax32(0, center.fLeft);
2105 c.fTop = SkMax32(0, center.fTop);
2106 c.fRight = SkPin32(center.fRight, c.fLeft, w);
2107 c.fBottom = SkPin32(center.fBottom, c.fTop, h);
2108
2109 const SkScalar srcX[4] = {
2110 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
2111 };
2112 const SkScalar srcY[4] = {
2113 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
2114 };
2115 SkScalar dstX[4] = {
2116 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
2117 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
2118 };
2119 SkScalar dstY[4] = {
2120 dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
2121 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
2122 };
2123
2124 if (dstX[1] > dstX[2]) {
2125 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
2126 dstX[2] = dstX[1];
2127 }
2128
2129 if (dstY[1] > dstY[2]) {
2130 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
2131 dstY[2] = dstY[1];
2132 }
2133
2134 for (int y = 0; y < 3; y++) {
2135 SkRect s, d;
2136
2137 s.fTop = srcY[y];
2138 s.fBottom = srcY[y+1];
2139 d.fTop = dstY[y];
2140 d.fBottom = dstY[y+1];
2141 for (int x = 0; x < 3; x++) {
2142 s.fLeft = srcX[x];
2143 s.fRight = srcX[x+1];
2144 d.fLeft = dstX[x];
2145 d.fRight = dstX[x+1];
2146 this->internalDrawBitmapRect(bitmap, &s, d, paint,
2147 kNone_DrawBitmapRectFlag);
2148 }
2149 }
2150 }
2151
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2152 void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2153 const SkPaint* paint) {
2154 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2155 SkDEBUGCODE(bitmap.validate();)
2156
2157 // Need a device entry-point, so gpu can use a mesh
2158 this->internalDrawBitmapNine(bitmap, center, dst, paint);
2159 }
2160
2161 class SkDeviceFilteredPaint {
2162 public:
SkDeviceFilteredPaint(SkBaseDevice * device,const SkPaint & paint)2163 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2164 uint32_t filteredFlags = device->filterTextFlags(paint);
2165 if (filteredFlags != paint.getFlags()) {
2166 SkPaint* newPaint = fLazy.set(paint);
2167 newPaint->setFlags(filteredFlags);
2168 fPaint = newPaint;
2169 } else {
2170 fPaint = &paint;
2171 }
2172 }
2173
paint() const2174 const SkPaint& paint() const { return *fPaint; }
2175
2176 private:
2177 const SkPaint* fPaint;
2178 SkLazyPaint fLazy;
2179 };
2180
DrawRect(const SkDraw & draw,const SkPaint & paint,const SkRect & r,SkScalar textSize)2181 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2182 const SkRect& r, SkScalar textSize) {
2183 if (paint.getStyle() == SkPaint::kFill_Style) {
2184 draw.fDevice->drawRect(draw, r, paint);
2185 } else {
2186 SkPaint p(paint);
2187 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2188 draw.fDevice->drawRect(draw, r, p);
2189 }
2190 }
2191
DrawTextDecorations(const SkDraw & draw,const SkPaint & paint,const char text[],size_t byteLength,SkScalar x,SkScalar y)2192 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2193 const char text[], size_t byteLength,
2194 SkScalar x, SkScalar y) {
2195 SkASSERT(byteLength == 0 || text != NULL);
2196
2197 // nothing to draw
2198 if (text == NULL || byteLength == 0 ||
2199 draw.fClip->isEmpty() ||
2200 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2201 return;
2202 }
2203
2204 SkScalar width = 0;
2205 SkPoint start;
2206
2207 start.set(0, 0); // to avoid warning
2208 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2209 SkPaint::kStrikeThruText_Flag)) {
2210 width = paint.measureText(text, byteLength);
2211
2212 SkScalar offsetX = 0;
2213 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2214 offsetX = SkScalarHalf(width);
2215 } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2216 offsetX = width;
2217 }
2218 start.set(x - offsetX, y);
2219 }
2220
2221 if (0 == width) {
2222 return;
2223 }
2224
2225 uint32_t flags = paint.getFlags();
2226
2227 if (flags & (SkPaint::kUnderlineText_Flag |
2228 SkPaint::kStrikeThruText_Flag)) {
2229 SkScalar textSize = paint.getTextSize();
2230 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2231 SkRect r;
2232
2233 r.fLeft = start.fX;
2234 r.fRight = start.fX + width;
2235
2236 if (flags & SkPaint::kUnderlineText_Flag) {
2237 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2238 start.fY);
2239 r.fTop = offset;
2240 r.fBottom = offset + height;
2241 DrawRect(draw, paint, r, textSize);
2242 }
2243 if (flags & SkPaint::kStrikeThruText_Flag) {
2244 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2245 start.fY);
2246 r.fTop = offset;
2247 r.fBottom = offset + height;
2248 DrawRect(draw, paint, r, textSize);
2249 }
2250 }
2251 }
2252
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)2253 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2254 const SkPaint& paint) {
2255 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2256
2257 while (iter.next()) {
2258 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2259 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2260 DrawTextDecorations(iter, dfp.paint(),
2261 static_cast<const char*>(text), byteLength, x, y);
2262 }
2263
2264 LOOPER_END
2265 }
2266
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2267 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2268 const SkPaint& paint) {
2269 SkPoint textOffset = SkPoint::Make(0, 0);
2270
2271 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2272
2273 while (iter.next()) {
2274 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2275 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2276 dfp.paint());
2277 }
2278
2279 LOOPER_END
2280 }
2281
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2282 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2283 SkScalar constY, const SkPaint& paint) {
2284
2285 SkPoint textOffset = SkPoint::Make(0, constY);
2286
2287 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2288
2289 while (iter.next()) {
2290 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2291 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2292 dfp.paint());
2293 }
2294
2295 LOOPER_END
2296 }
2297
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2298 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2299 const SkMatrix* matrix, const SkPaint& paint) {
2300 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
2301
2302 while (iter.next()) {
2303 iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2304 matrix, looper.paint());
2305 }
2306
2307 LOOPER_END
2308 }
2309
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2310 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2311 const SkPaint& paint) {
2312
2313 SkRect storage;
2314 const SkRect* bounds = NULL;
2315 if (paint.canComputeFastBounds()) {
2316 storage = blob->bounds().makeOffset(x, y);
2317 bounds = &paint.computeFastBounds(storage, &storage);
2318
2319 if (this->quickReject(*bounds)) {
2320 return;
2321 }
2322 }
2323
2324 // We cannot filter in the looper as we normally do, because the paint is
2325 // incomplete at this point (text-related attributes are embedded within blob run paints).
2326 SkDrawFilter* drawFilter = fMCRec->fFilter;
2327 fMCRec->fFilter = NULL;
2328
2329 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2330
2331 while (iter.next()) {
2332 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2333 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
2334 }
2335
2336 LOOPER_END
2337
2338 fMCRec->fFilter = drawFilter;
2339 }
2340
2341 // These will become non-virtual, so they always call the (virtual) onDraw... method
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)2342 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2343 const SkPaint& paint) {
2344 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2345 this->onDrawText(text, byteLength, x, y, paint);
2346 }
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2347 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2348 const SkPaint& paint) {
2349 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2350 this->onDrawPosText(text, byteLength, pos, paint);
2351 }
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2352 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2353 SkScalar constY, const SkPaint& paint) {
2354 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2355 this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2356 }
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2357 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2358 const SkMatrix* matrix, const SkPaint& paint) {
2359 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2360 this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2361 }
drawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2362 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2363 const SkPaint& paint) {
2364 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2365 if (blob) {
2366 this->onDrawTextBlob(blob, x, y, paint);
2367 }
2368 }
2369
onDrawVertices(VertexMode vmode,int vertexCount,const SkPoint verts[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)2370 void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
2371 const SkPoint verts[], const SkPoint texs[],
2372 const SkColor colors[], SkXfermode* xmode,
2373 const uint16_t indices[], int indexCount,
2374 const SkPaint& paint) {
2375 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2376 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2377
2378 while (iter.next()) {
2379 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2380 colors, xmode, indices, indexCount,
2381 looper.paint());
2382 }
2383
2384 LOOPER_END
2385 }
2386
drawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)2387 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2388 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2389 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2390 if (NULL == cubics) {
2391 return;
2392 }
2393
2394 // Since a patch is always within the convex hull of the control points, we discard it when its
2395 // bounding rectangle is completely outside the current clip.
2396 SkRect bounds;
2397 bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2398 if (this->quickReject(bounds)) {
2399 return;
2400 }
2401
2402 this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2403 }
2404
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)2405 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2406 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2407
2408 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
2409
2410 while (iter.next()) {
2411 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2412 }
2413
2414 LOOPER_END
2415 }
2416
drawDrawable(SkDrawable * dr)2417 void SkCanvas::drawDrawable(SkDrawable* dr) {
2418 if (dr && !this->quickReject(dr->getBounds())) {
2419 this->onDrawDrawable(dr);
2420 }
2421 }
2422
onDrawDrawable(SkDrawable * dr)2423 void SkCanvas::onDrawDrawable(SkDrawable* dr) {
2424 dr->draw(this);
2425 }
2426
2427 //////////////////////////////////////////////////////////////////////////////
2428 // These methods are NOT virtual, and therefore must call back into virtual
2429 // methods, rather than actually drawing themselves.
2430 //////////////////////////////////////////////////////////////////////////////
2431
drawARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b,SkXfermode::Mode mode)2432 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2433 SkXfermode::Mode mode) {
2434 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
2435 SkPaint paint;
2436
2437 paint.setARGB(a, r, g, b);
2438 if (SkXfermode::kSrcOver_Mode != mode) {
2439 paint.setXfermodeMode(mode);
2440 }
2441 this->drawPaint(paint);
2442 }
2443
drawColor(SkColor c,SkXfermode::Mode mode)2444 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2445 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2446 SkPaint paint;
2447
2448 paint.setColor(c);
2449 if (SkXfermode::kSrcOver_Mode != mode) {
2450 paint.setXfermodeMode(mode);
2451 }
2452 this->drawPaint(paint);
2453 }
2454
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)2455 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2456 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2457 SkPoint pt;
2458
2459 pt.set(x, y);
2460 this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2461 }
2462
drawPoint(SkScalar x,SkScalar y,SkColor color)2463 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2464 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
2465 SkPoint pt;
2466 SkPaint paint;
2467
2468 pt.set(x, y);
2469 paint.setColor(color);
2470 this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2471 }
2472
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)2473 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2474 const SkPaint& paint) {
2475 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2476 SkPoint pts[2];
2477
2478 pts[0].set(x0, y0);
2479 pts[1].set(x1, y1);
2480 this->drawPoints(kLines_PointMode, 2, pts, paint);
2481 }
2482
drawRectCoords(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom,const SkPaint & paint)2483 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2484 SkScalar right, SkScalar bottom,
2485 const SkPaint& paint) {
2486 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
2487 SkRect r;
2488
2489 r.set(left, top, right, bottom);
2490 this->drawRect(r, paint);
2491 }
2492
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)2493 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2494 const SkPaint& paint) {
2495 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2496 if (radius < 0) {
2497 radius = 0;
2498 }
2499
2500 SkRect r;
2501 r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2502 this->drawOval(r, paint);
2503 }
2504
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)2505 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2506 const SkPaint& paint) {
2507 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2508 if (rx > 0 && ry > 0) {
2509 if (paint.canComputeFastBounds()) {
2510 SkRect storage;
2511 if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2512 return;
2513 }
2514 }
2515 SkRRect rrect;
2516 rrect.setRectXY(r, rx, ry);
2517 this->drawRRect(rrect, paint);
2518 } else {
2519 this->drawRect(r, paint);
2520 }
2521 }
2522
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2523 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2524 SkScalar sweepAngle, bool useCenter,
2525 const SkPaint& paint) {
2526 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2527 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2528 this->drawOval(oval, paint);
2529 } else {
2530 SkPath path;
2531 if (useCenter) {
2532 path.moveTo(oval.centerX(), oval.centerY());
2533 }
2534 path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2535 if (useCenter) {
2536 path.close();
2537 }
2538 this->drawPath(path, paint);
2539 }
2540 }
2541
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)2542 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2543 const SkPath& path, SkScalar hOffset,
2544 SkScalar vOffset, const SkPaint& paint) {
2545 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2546 SkMatrix matrix;
2547
2548 matrix.setTranslate(hOffset, vOffset);
2549 this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2550 }
2551
2552 ///////////////////////////////////////////////////////////////////////////////
2553
2554 /**
2555 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2556 * against the playback cost of recursing into the subpicture to get at its actual ops.
2557 *
2558 * For now we pick a conservatively small value, though measurement (and other heuristics like
2559 * the type of ops contained) may justify changing this value.
2560 */
2561 #define kMaxPictureOpsToUnrollInsteadOfRef 1
2562
drawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2563 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2564 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2565 if (picture) {
2566 if (matrix && matrix->isIdentity()) {
2567 matrix = NULL;
2568 }
2569 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2570 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2571 picture->playback(this);
2572 } else {
2573 this->onDrawPicture(picture, matrix, paint);
2574 }
2575 }
2576 }
2577
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2578 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2579 const SkPaint* paint) {
2580 SkBaseDevice* device = this->getTopDevice();
2581 if (device) {
2582 // Canvas has to first give the device the opportunity to render
2583 // the picture itself.
2584 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2585 return; // the device has rendered the entire picture
2586 }
2587 }
2588
2589 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2590 picture->playback(this);
2591 }
2592
2593 ///////////////////////////////////////////////////////////////////////////////
2594 ///////////////////////////////////////////////////////////////////////////////
2595
LayerIter(SkCanvas * canvas,bool skipEmptyClips)2596 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2597 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2598
2599 SkASSERT(canvas);
2600
2601 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2602 fDone = !fImpl->next();
2603 }
2604
~LayerIter()2605 SkCanvas::LayerIter::~LayerIter() {
2606 fImpl->~SkDrawIter();
2607 }
2608
next()2609 void SkCanvas::LayerIter::next() {
2610 fDone = !fImpl->next();
2611 }
2612
device() const2613 SkBaseDevice* SkCanvas::LayerIter::device() const {
2614 return fImpl->getDevice();
2615 }
2616
matrix() const2617 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2618 return fImpl->getMatrix();
2619 }
2620
paint() const2621 const SkPaint& SkCanvas::LayerIter::paint() const {
2622 const SkPaint* paint = fImpl->getPaint();
2623 if (NULL == paint) {
2624 paint = &fDefaultPaint;
2625 }
2626 return *paint;
2627 }
2628
clip() const2629 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
x() const2630 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const2631 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2632
2633 ///////////////////////////////////////////////////////////////////////////////
2634
~SkCanvasClipVisitor()2635 SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2636
2637 ///////////////////////////////////////////////////////////////////////////////
2638
supported_for_raster_canvas(const SkImageInfo & info)2639 static bool supported_for_raster_canvas(const SkImageInfo& info) {
2640 switch (info.alphaType()) {
2641 case kPremul_SkAlphaType:
2642 case kOpaque_SkAlphaType:
2643 break;
2644 default:
2645 return false;
2646 }
2647
2648 switch (info.colorType()) {
2649 case kAlpha_8_SkColorType:
2650 case kRGB_565_SkColorType:
2651 case kN32_SkColorType:
2652 break;
2653 default:
2654 return false;
2655 }
2656
2657 return true;
2658 }
2659
NewRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes)2660 SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2661 if (!supported_for_raster_canvas(info)) {
2662 return NULL;
2663 }
2664
2665 SkBitmap bitmap;
2666 if (!bitmap.installPixels(info, pixels, rowBytes)) {
2667 return NULL;
2668 }
2669 return SkNEW_ARGS(SkCanvas, (bitmap));
2670 }
2671
2672 ///////////////////////////////////////////////////////////////////////////////
2673
SkAutoCanvasMatrixPaint(SkCanvas * canvas,const SkMatrix * matrix,const SkPaint * paint,const SkRect & bounds)2674 SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2675 const SkPaint* paint, const SkRect& bounds)
2676 : fCanvas(canvas)
2677 , fSaveCount(canvas->getSaveCount())
2678 {
2679 if (paint) {
2680 SkRect newBounds = bounds;
2681 if (matrix) {
2682 matrix->mapRect(&newBounds);
2683 }
2684 canvas->saveLayer(&newBounds, paint);
2685 } else if (matrix) {
2686 canvas->save();
2687 }
2688
2689 if (matrix) {
2690 canvas->concat(*matrix);
2691 }
2692 }
2693
~SkAutoCanvasMatrixPaint()2694 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2695 fCanvas->restoreToCount(fSaveCount);
2696 }
2697