• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2008 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkCanvas.h"
11 #include "SkBounder.h"
12 #include "SkDevice.h"
13 #include "SkDeviceImageFilterProxy.h"
14 #include "SkDraw.h"
15 #include "SkDrawFilter.h"
16 #include "SkDrawLooper.h"
17 #include "SkMetaData.h"
18 #include "SkPicture.h"
19 #include "SkRasterClip.h"
20 #include "SkRRect.h"
21 #include "SkScalarCompare.h"
22 #include "SkSurface_Base.h"
23 #include "SkTemplates.h"
24 #include "SkTextFormatParams.h"
25 #include "SkTLazy.h"
26 #include "SkUtils.h"
27 
28 SK_DEFINE_INST_COUNT(SkBounder)
29 SK_DEFINE_INST_COUNT(SkCanvas)
30 SK_DEFINE_INST_COUNT(SkDrawFilter)
31 
32 // experimental for faster tiled drawing...
33 //#define SK_ENABLE_CLIP_QUICKREJECT
34 
35 //#define SK_TRACE_SAVERESTORE
36 
37 #ifdef SK_TRACE_SAVERESTORE
38     static int gLayerCounter;
inc_layer()39     static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
dec_layer()40     static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
41 
42     static int gRecCounter;
inc_rec()43     static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
dec_rec()44     static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
45 
46     static int gCanvasCounter;
inc_canvas()47     static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
dec_canvas()48     static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
49 #else
50     #define inc_layer()
51     #define dec_layer()
52     #define inc_rec()
53     #define dec_rec()
54     #define inc_canvas()
55     #define dec_canvas()
56 #endif
57 
58 #ifdef SK_DEBUG
59 #include "SkPixelRef.h"
60 
61 /*
62  *  Some pixelref subclasses can support being "locked" from another thread
63  *  during the lock-scope of skia calling them. In these instances, this balance
64  *  check will fail, but may not be indicative of a problem, so we allow a build
65  *  flag to disable this check.
66  *
67  *  Potentially another fix would be to have a (debug-only) virtual or flag on
68  *  pixelref, which could tell us at runtime if this check is valid. That would
69  *  eliminate the need for this heavy-handed build check.
70  */
71 #ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK
72 class AutoCheckLockCountBalance {
73 public:
AutoCheckLockCountBalance(const SkBitmap &)74     AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
75 };
76 #else
77 class AutoCheckLockCountBalance {
78 public:
AutoCheckLockCountBalance(const SkBitmap & bm)79     AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
80         fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
81     }
~AutoCheckLockCountBalance()82     ~AutoCheckLockCountBalance() {
83         const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
84         SkASSERT(count == fLockCount);
85     }
86 
87 private:
88     const SkPixelRef* fPixelRef;
89     int               fLockCount;
90 };
91 #endif
92 
93 class AutoCheckNoSetContext {
94 public:
AutoCheckNoSetContext(const SkPaint & paint)95     AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) {
96         this->assertNoSetContext(fPaint);
97     }
~AutoCheckNoSetContext()98     ~AutoCheckNoSetContext() {
99         this->assertNoSetContext(fPaint);
100     }
101 
102 private:
103     const SkPaint& fPaint;
104 
assertNoSetContext(const SkPaint & paint)105     void assertNoSetContext(const SkPaint& paint) {
106         SkShader* s = paint.getShader();
107         if (s) {
108             SkASSERT(!s->setContextHasBeenCalled());
109         }
110     }
111 };
112 
113 #define CHECK_LOCKCOUNT_BALANCE(bitmap)  AutoCheckLockCountBalance clcb(bitmap)
114 #define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext     cshsc(paint)
115 
116 #else
117     #define CHECK_LOCKCOUNT_BALANCE(bitmap)
118     #define CHECK_SHADER_NOSETCONTEXT(paint)
119 #endif
120 
121 typedef SkTLazy<SkPaint> SkLazyPaint;
122 
predrawNotify()123 void SkCanvas::predrawNotify() {
124     if (fSurfaceBase) {
125         fSurfaceBase->aboutToDraw(this);
126     }
127 }
128 
129 ///////////////////////////////////////////////////////////////////////////////
130 
131 /*  This is the record we keep for each SkDevice that the user installs.
132     The clip/matrix/proc are fields that reflect the top of the save/restore
133     stack. Whenever the canvas changes, it marks a dirty flag, and then before
134     these are used (assuming we're not on a layer) we rebuild these cache
135     values: they reflect the top of the save stack, but translated and clipped
136     by the device's XY offset and bitmap-bounds.
137 */
138 struct DeviceCM {
139     DeviceCM*           fNext;
140     SkDevice*           fDevice;
141     SkRasterClip        fClip;
142     const SkMatrix*     fMatrix;
143     SkPaint*            fPaint; // may be null (in the future)
144 
DeviceCMDeviceCM145     DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
146             : fNext(NULL) {
147         if (NULL != device) {
148             device->ref();
149             device->onAttachToCanvas(canvas);
150         }
151         fDevice = device;
152         fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
153     }
154 
~DeviceCMDeviceCM155     ~DeviceCM() {
156         if (NULL != fDevice) {
157             fDevice->onDetachFromCanvas();
158             fDevice->unref();
159         }
160         SkDELETE(fPaint);
161     }
162 
updateMCDeviceCM163     void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
164                   const SkClipStack& clipStack, SkRasterClip* updateClip) {
165         int x = fDevice->getOrigin().x();
166         int y = fDevice->getOrigin().y();
167         int width = fDevice->width();
168         int height = fDevice->height();
169 
170         if ((x | y) == 0) {
171             fMatrix = &totalMatrix;
172             fClip = totalClip;
173         } else {
174             fMatrixStorage = totalMatrix;
175             fMatrixStorage.postTranslate(SkIntToScalar(-x),
176                                          SkIntToScalar(-y));
177             fMatrix = &fMatrixStorage;
178 
179             totalClip.translate(-x, -y, &fClip);
180         }
181 
182         fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
183 
184         // intersect clip, but don't translate it (yet)
185 
186         if (updateClip) {
187             updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
188                            SkRegion::kDifference_Op);
189         }
190 
191         fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
192 
193 #ifdef SK_DEBUG
194         if (!fClip.isEmpty()) {
195             SkIRect deviceR;
196             deviceR.set(0, 0, width, height);
197             SkASSERT(deviceR.contains(fClip.getBounds()));
198         }
199 #endif
200     }
201 
202 private:
203     SkMatrix    fMatrixStorage;
204 };
205 
206 /*  This is the record we keep for each save/restore level in the stack.
207     Since a level optionally copies the matrix and/or stack, we have pointers
208     for these fields. If the value is copied for this level, the copy is
209     stored in the ...Storage field, and the pointer points to that. If the
210     value is not copied for this level, we ignore ...Storage, and just point
211     at the corresponding value in the previous level in the stack.
212 */
213 class SkCanvas::MCRec {
214 public:
215     MCRec*          fNext;
216     SkMatrix*       fMatrix;        // points to either fMatrixStorage or prev MCRec
217     SkRasterClip*   fRasterClip;    // points to either fRegionStorage or prev MCRec
218     SkDrawFilter*   fFilter;        // the current filter (or null)
219 
220     DeviceCM*   fLayer;
221     /*  If there are any layers in the stack, this points to the top-most
222         one that is at or below this level in the stack (so we know what
223         bitmap/device to draw into from this level. This value is NOT
224         reference counted, since the real owner is either our fLayer field,
225         or a previous one in a lower level.)
226     */
227     DeviceCM*   fTopLayer;
228 
MCRec(const MCRec * prev,int flags)229     MCRec(const MCRec* prev, int flags) {
230         if (NULL != prev) {
231             if (flags & SkCanvas::kMatrix_SaveFlag) {
232                 fMatrixStorage = *prev->fMatrix;
233                 fMatrix = &fMatrixStorage;
234             } else {
235                 fMatrix = prev->fMatrix;
236             }
237 
238             if (flags & SkCanvas::kClip_SaveFlag) {
239                 fRasterClipStorage = *prev->fRasterClip;
240                 fRasterClip = &fRasterClipStorage;
241             } else {
242                 fRasterClip = prev->fRasterClip;
243             }
244 
245             fFilter = prev->fFilter;
246             SkSafeRef(fFilter);
247 
248             fTopLayer = prev->fTopLayer;
249         } else {   // no prev
250             fMatrixStorage.reset();
251 
252             fMatrix     = &fMatrixStorage;
253             fRasterClip = &fRasterClipStorage;
254             fFilter     = NULL;
255             fTopLayer   = NULL;
256         }
257         fLayer = NULL;
258 
259         // don't bother initializing fNext
260         inc_rec();
261     }
~MCRec()262     ~MCRec() {
263         SkSafeUnref(fFilter);
264         SkDELETE(fLayer);
265         dec_rec();
266     }
267 
268 private:
269     SkMatrix        fMatrixStorage;
270     SkRasterClip    fRasterClipStorage;
271 };
272 
273 class SkDrawIter : public SkDraw {
274 public:
SkDrawIter(SkCanvas * canvas,bool skipEmptyClips=true)275     SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
276         canvas = canvas->canvasForDrawIter();
277         fCanvas = canvas;
278         canvas->updateDeviceCMCache();
279 
280         fClipStack = &canvas->fClipStack;
281         fBounder = canvas->getBounder();
282         fCurrLayer = canvas->fMCRec->fTopLayer;
283         fSkipEmptyClips = skipEmptyClips;
284     }
285 
next()286     bool next() {
287         // skip over recs with empty clips
288         if (fSkipEmptyClips) {
289             while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
290                 fCurrLayer = fCurrLayer->fNext;
291             }
292         }
293 
294         const DeviceCM* rec = fCurrLayer;
295         if (rec && rec->fDevice) {
296 
297             fMatrix = rec->fMatrix;
298             fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
299             fRC     = &rec->fClip;
300             fDevice = rec->fDevice;
301             fBitmap = &fDevice->accessBitmap(true);
302             fPaint  = rec->fPaint;
303             SkDEBUGCODE(this->validate();)
304 
305             fCurrLayer = rec->fNext;
306             if (fBounder) {
307                 fBounder->setClip(fClip);
308             }
309             // fCurrLayer may be NULL now
310 
311             return true;
312         }
313         return false;
314     }
315 
getDevice() const316     SkDevice* getDevice() const { return fDevice; }
getX() const317     int getX() const { return fDevice->getOrigin().x(); }
getY() const318     int getY() const { return fDevice->getOrigin().y(); }
getMatrix() const319     const SkMatrix& getMatrix() const { return *fMatrix; }
getClip() const320     const SkRegion& getClip() const { return *fClip; }
getPaint() const321     const SkPaint* getPaint() const { return fPaint; }
322 
323 private:
324     SkCanvas*       fCanvas;
325     const DeviceCM* fCurrLayer;
326     const SkPaint*  fPaint;     // May be null.
327     SkBool8         fSkipEmptyClips;
328 
329     typedef SkDraw INHERITED;
330 };
331 
332 /////////////////////////////////////////////////////////////////////////////
333 
334 class AutoDrawLooper {
335 public:
AutoDrawLooper(SkCanvas * canvas,const SkPaint & paint,bool skipLayerForImageFilter=false)336     AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
337                    bool skipLayerForImageFilter = false) : fOrigPaint(paint) {
338         fCanvas = canvas;
339         fLooper = paint.getLooper();
340         fFilter = canvas->getDrawFilter();
341         fPaint = NULL;
342         fSaveCount = canvas->getSaveCount();
343         fDoClearImageFilter = false;
344         fDone = false;
345 
346         if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
347             SkPaint tmp;
348             tmp.setImageFilter(fOrigPaint.getImageFilter());
349             // it would be nice if we had a guess at the bounds, instead of null
350             (void)canvas->internalSaveLayer(NULL, &tmp,
351                                     SkCanvas::kARGB_ClipLayer_SaveFlag, true);
352             // we'll clear the imageFilter for the actual draws in next(), so
353             // it will only be applied during the restore().
354             fDoClearImageFilter = true;
355         }
356 
357         if (fLooper) {
358             fLooper->init(canvas);
359             fIsSimple = false;
360         } else {
361             // can we be marked as simple?
362             fIsSimple = !fFilter && !fDoClearImageFilter;
363         }
364     }
365 
~AutoDrawLooper()366     ~AutoDrawLooper() {
367         if (fDoClearImageFilter) {
368             fCanvas->internalRestore();
369         }
370         SkASSERT(fCanvas->getSaveCount() == fSaveCount);
371     }
372 
paint() const373     const SkPaint& paint() const {
374         SkASSERT(fPaint);
375         return *fPaint;
376     }
377 
next(SkDrawFilter::Type drawType)378     bool next(SkDrawFilter::Type drawType) {
379         if (fDone) {
380             return false;
381         } else if (fIsSimple) {
382             fDone = true;
383             fPaint = &fOrigPaint;
384             return !fPaint->nothingToDraw();
385         } else {
386             return this->doNext(drawType);
387         }
388     }
389 
390 private:
391     SkLazyPaint     fLazyPaint;
392     SkCanvas*       fCanvas;
393     const SkPaint&  fOrigPaint;
394     SkDrawLooper*   fLooper;
395     SkDrawFilter*   fFilter;
396     const SkPaint*  fPaint;
397     int             fSaveCount;
398     bool            fDoClearImageFilter;
399     bool            fDone;
400     bool            fIsSimple;
401 
402     bool doNext(SkDrawFilter::Type drawType);
403 };
404 
doNext(SkDrawFilter::Type drawType)405 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
406     fPaint = NULL;
407     SkASSERT(!fIsSimple);
408     SkASSERT(fLooper || fFilter || fDoClearImageFilter);
409 
410     SkPaint* paint = fLazyPaint.set(fOrigPaint);
411 
412     if (fDoClearImageFilter) {
413         paint->setImageFilter(NULL);
414     }
415 
416     if (fLooper && !fLooper->next(fCanvas, paint)) {
417         fDone = true;
418         return false;
419     }
420     if (fFilter) {
421         if (!fFilter->filter(paint, drawType)) {
422             fDone = true;
423             return false;
424         }
425         if (NULL == fLooper) {
426             // no looper means we only draw once
427             fDone = true;
428         }
429     }
430     fPaint = paint;
431 
432     // if we only came in here for the imagefilter, mark us as done
433     if (!fLooper && !fFilter) {
434         fDone = true;
435     }
436 
437     // call this after any possible paint modifiers
438     if (fPaint->nothingToDraw()) {
439         fPaint = NULL;
440         return false;
441     }
442     return true;
443 }
444 
445 /*  Stack helper for managing a SkBounder. In the destructor, if we were
446     given a bounder, we call its commit() method, signifying that we are
447     done accumulating bounds for that draw.
448 */
449 class SkAutoBounderCommit {
450 public:
SkAutoBounderCommit(SkBounder * bounder)451     SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
~SkAutoBounderCommit()452     ~SkAutoBounderCommit() {
453         if (NULL != fBounder) {
454             fBounder->commit();
455         }
456     }
457 private:
458     SkBounder*  fBounder;
459 };
460 
461 #include "SkColorPriv.h"
462 
463 class AutoValidator {
464 public:
AutoValidator(SkDevice * device)465     AutoValidator(SkDevice* device) : fDevice(device) {}
~AutoValidator()466     ~AutoValidator() {
467 #ifdef SK_DEBUG
468         const SkBitmap& bm = fDevice->accessBitmap(false);
469         if (bm.config() == SkBitmap::kARGB_4444_Config) {
470             for (int y = 0; y < bm.height(); y++) {
471                 const SkPMColor16* p = bm.getAddr16(0, y);
472                 for (int x = 0; x < bm.width(); x++) {
473                     SkPMColor16 c = p[x];
474                     SkPMColor16Assert(c);
475                 }
476             }
477         }
478 #endif
479     }
480 private:
481     SkDevice* fDevice;
482 };
483 
484 ////////// macros to place around the internal draw calls //////////////////
485 
486 #define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
487 /*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
488     this->predrawNotify();                                          \
489     AutoDrawLooper  looper(this, paint, true);                      \
490     while (looper.next(type)) {                                     \
491         SkAutoBounderCommit ac(fBounder);                           \
492         SkDrawIter          iter(this);
493 
494 #define LOOPER_BEGIN(paint, type)                                   \
495 /*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
496     this->predrawNotify();                                          \
497     AutoDrawLooper  looper(this, paint);                            \
498     while (looper.next(type)) {                                     \
499         SkAutoBounderCommit ac(fBounder);                           \
500         SkDrawIter          iter(this);
501 
502 #define LOOPER_END    }
503 
504 ////////////////////////////////////////////////////////////////////////////
505 
init(SkDevice * device)506 SkDevice* SkCanvas::init(SkDevice* device) {
507     fBounder = NULL;
508     fLocalBoundsCompareType.setEmpty();
509     fLocalBoundsCompareTypeDirty = true;
510     fAllowSoftClip = true;
511     fDeviceCMDirty = false;
512     fSaveLayerCount = 0;
513     fMetaData = NULL;
514 
515     fMCRec = (MCRec*)fMCStack.push_back();
516     new (fMCRec) MCRec(NULL, 0);
517 
518     fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
519     fMCRec->fTopLayer = fMCRec->fLayer;
520     fMCRec->fNext = NULL;
521 
522     fSurfaceBase = NULL;
523 
524     return this->setDevice(device);
525 }
526 
SkCanvas()527 SkCanvas::SkCanvas()
528 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
529     inc_canvas();
530 
531     this->init(NULL);
532 }
533 
SkCanvas(SkDevice * device)534 SkCanvas::SkCanvas(SkDevice* device)
535         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
536     inc_canvas();
537 
538     this->init(device);
539 }
540 
SkCanvas(const SkBitmap & bitmap)541 SkCanvas::SkCanvas(const SkBitmap& bitmap)
542         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
543     inc_canvas();
544 
545     this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
546 }
547 
~SkCanvas()548 SkCanvas::~SkCanvas() {
549     // free up the contents of our deque
550     this->restoreToCount(1);    // restore everything but the last
551     SkASSERT(0 == fSaveLayerCount);
552 
553     this->internalRestore();    // restore the last, since we're going away
554 
555     SkSafeUnref(fBounder);
556     SkDELETE(fMetaData);
557 
558     dec_canvas();
559 }
560 
setBounder(SkBounder * bounder)561 SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
562     SkRefCnt_SafeAssign(fBounder, bounder);
563     return bounder;
564 }
565 
getDrawFilter() const566 SkDrawFilter* SkCanvas::getDrawFilter() const {
567     return fMCRec->fFilter;
568 }
569 
setDrawFilter(SkDrawFilter * filter)570 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
571     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
572     return filter;
573 }
574 
getMetaData()575 SkMetaData& SkCanvas::getMetaData() {
576     // metadata users are rare, so we lazily allocate it. If that changes we
577     // can decide to just make it a field in the device (rather than a ptr)
578     if (NULL == fMetaData) {
579         fMetaData = new SkMetaData;
580     }
581     return *fMetaData;
582 }
583 
584 ///////////////////////////////////////////////////////////////////////////////
585 
flush()586 void SkCanvas::flush() {
587     SkDevice* device = this->getDevice();
588     if (device) {
589         device->flush();
590     }
591 }
592 
getDeviceSize() const593 SkISize SkCanvas::getDeviceSize() const {
594     SkDevice* d = this->getDevice();
595     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
596 }
597 
getDevice() const598 SkDevice* SkCanvas::getDevice() const {
599     // return root device
600     MCRec* rec = (MCRec*) fMCStack.front();
601     SkASSERT(rec && rec->fLayer);
602     return rec->fLayer->fDevice;
603 }
604 
getTopDevice(bool updateMatrixClip) const605 SkDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
606     if (updateMatrixClip) {
607         const_cast<SkCanvas*>(this)->updateDeviceCMCache();
608     }
609     return fMCRec->fTopLayer->fDevice;
610 }
611 
setDevice(SkDevice * device)612 SkDevice* SkCanvas::setDevice(SkDevice* device) {
613     // return root device
614     SkDeque::F2BIter iter(fMCStack);
615     MCRec*           rec = (MCRec*)iter.next();
616     SkASSERT(rec && rec->fLayer);
617     SkDevice*       rootDevice = rec->fLayer->fDevice;
618 
619     if (rootDevice == device) {
620         return device;
621     }
622 
623     if (device) {
624         device->onAttachToCanvas(this);
625     }
626     if (rootDevice) {
627         rootDevice->onDetachFromCanvas();
628     }
629 
630     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
631     rootDevice = device;
632 
633     fDeviceCMDirty = true;
634 
635     /*  Now we update our initial region to have the bounds of the new device,
636         and then intersect all of the clips in our stack with these bounds,
637         to ensure that we can't draw outside of the device's bounds (and trash
638                                                                      memory).
639 
640     NOTE: this is only a partial-fix, since if the new device is larger than
641         the previous one, we don't know how to "enlarge" the clips in our stack,
642         so drawing may be artificially restricted. Without keeping a history of
643         all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
644         reconstruct the correct clips, so this approximation will have to do.
645         The caller really needs to restore() back to the base if they want to
646         accurately take advantage of the new device bounds.
647     */
648 
649     SkIRect bounds;
650     if (device) {
651         bounds.set(0, 0, device->width(), device->height());
652     } else {
653         bounds.setEmpty();
654     }
655     // now jam our 1st clip to be bounds, and intersect the rest with that
656     rec->fRasterClip->setRect(bounds);
657     while ((rec = (MCRec*)iter.next()) != NULL) {
658         (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
659     }
660 
661     return device;
662 }
663 
readPixels(SkBitmap * bitmap,int x,int y,Config8888 config8888)664 bool SkCanvas::readPixels(SkBitmap* bitmap,
665                           int x, int y,
666                           Config8888 config8888) {
667     SkDevice* device = this->getDevice();
668     if (!device) {
669         return false;
670     }
671     return device->readPixels(bitmap, x, y, config8888);
672 }
673 
readPixels(const SkIRect & srcRect,SkBitmap * bitmap)674 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
675     SkDevice* device = this->getDevice();
676     if (!device) {
677         return false;
678     }
679 
680     SkIRect bounds;
681     bounds.set(0, 0, device->width(), device->height());
682     if (!bounds.intersect(srcRect)) {
683         return false;
684     }
685 
686     SkBitmap tmp;
687     tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
688                                                bounds.height());
689     if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
690         bitmap->swap(tmp);
691         return true;
692     } else {
693         return false;
694     }
695 }
696 
writePixels(const SkBitmap & bitmap,int x,int y,Config8888 config8888)697 void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y,
698                            Config8888 config8888) {
699     SkDevice* device = this->getDevice();
700     if (device) {
701         if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()),
702                                 SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) {
703             device->accessBitmap(true);
704             device->writePixels(bitmap, x, y, config8888);
705         }
706     }
707 }
708 
canvasForDrawIter()709 SkCanvas* SkCanvas::canvasForDrawIter() {
710     return this;
711 }
712 
713 //////////////////////////////////////////////////////////////////////////////
714 
updateDeviceCMCache()715 void SkCanvas::updateDeviceCMCache() {
716     if (fDeviceCMDirty) {
717         const SkMatrix& totalMatrix = this->getTotalMatrix();
718         const SkRasterClip& totalClip = *fMCRec->fRasterClip;
719         DeviceCM*       layer = fMCRec->fTopLayer;
720 
721         if (NULL == layer->fNext) {   // only one layer
722             layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
723         } else {
724             SkRasterClip clip(totalClip);
725             do {
726                 layer->updateMC(totalMatrix, clip, fClipStack, &clip);
727             } while ((layer = layer->fNext) != NULL);
728         }
729         fDeviceCMDirty = false;
730     }
731 }
732 
733 ///////////////////////////////////////////////////////////////////////////////
734 
internalSave(SaveFlags flags)735 int SkCanvas::internalSave(SaveFlags flags) {
736     int saveCount = this->getSaveCount(); // record this before the actual save
737 
738     MCRec* newTop = (MCRec*)fMCStack.push_back();
739     new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
740 
741     newTop->fNext = fMCRec;
742     fMCRec = newTop;
743 
744     fClipStack.save();
745     SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
746 
747     return saveCount;
748 }
749 
save(SaveFlags flags)750 int SkCanvas::save(SaveFlags flags) {
751     // call shared impl
752     return this->internalSave(flags);
753 }
754 
755 #define C32MASK (1 << SkBitmap::kARGB_8888_Config)
756 #define C16MASK (1 << SkBitmap::kRGB_565_Config)
757 #define C8MASK  (1 << SkBitmap::kA8_Config)
758 
resolve_config(SkCanvas * canvas,const SkIRect & bounds,SkCanvas::SaveFlags flags,bool * isOpaque)759 static SkBitmap::Config resolve_config(SkCanvas* canvas,
760                                        const SkIRect& bounds,
761                                        SkCanvas::SaveFlags flags,
762                                        bool* isOpaque) {
763     *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
764 
765 #if 0
766     // loop through and union all the configs we may draw into
767     uint32_t configMask = 0;
768     for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
769     {
770         SkDevice* device = canvas->getLayerDevice(i);
771         if (device->intersects(bounds))
772             configMask |= 1 << device->config();
773     }
774 
775     // if the caller wants alpha or fullcolor, we can't return 565
776     if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
777                  SkCanvas::kHasAlphaLayer_SaveFlag))
778         configMask &= ~C16MASK;
779 
780     switch (configMask) {
781     case C8MASK:    // if we only have A8, return that
782         return SkBitmap::kA8_Config;
783 
784     case C16MASK:   // if we only have 565, return that
785         return SkBitmap::kRGB_565_Config;
786 
787     default:
788         return SkBitmap::kARGB_8888_Config; // default answer
789     }
790 #else
791     return SkBitmap::kARGB_8888_Config; // default answer
792 #endif
793 }
794 
bounds_affects_clip(SkCanvas::SaveFlags flags)795 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
796     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
797 }
798 
clipRectBounds(const SkRect * bounds,SaveFlags flags,SkIRect * intersection)799 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
800                                SkIRect* intersection) {
801     SkIRect clipBounds;
802     if (!this->getClipDeviceBounds(&clipBounds)) {
803         return false;
804     }
805     SkIRect ir;
806     if (NULL != bounds) {
807         SkRect r;
808 
809         this->getTotalMatrix().mapRect(&r, *bounds);
810         r.roundOut(&ir);
811         // early exit if the layer's bounds are clipped out
812         if (!ir.intersect(clipBounds)) {
813             if (bounds_affects_clip(flags)) {
814                 fMCRec->fRasterClip->setEmpty();
815             }
816             return false;
817         }
818     } else {    // no user bounds, so just use the clip
819         ir = clipBounds;
820     }
821 
822     fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
823 
824     // early exit if the clip is now empty
825     if (bounds_affects_clip(flags) &&
826         !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) {
827         return false;
828     }
829 
830     if (intersection) {
831         *intersection = ir;
832     }
833     return true;
834 }
835 
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)836 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
837                         SaveFlags flags) {
838     return this->internalSaveLayer(bounds, paint, flags, false);
839 }
840 
internalSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags,bool justForImageFilter)841 int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
842                                 SaveFlags flags, bool justForImageFilter) {
843     // do this before we create the layer. We don't call the public save() since
844     // that would invoke a possibly overridden virtual
845     int count = this->internalSave(flags);
846 
847     fDeviceCMDirty = true;
848 
849     SkIRect ir;
850     if (!this->clipRectBounds(bounds, flags, &ir)) {
851         return count;
852     }
853 
854     // Kill the imagefilter if our device doesn't allow it
855     SkLazyPaint lazyP;
856     if (paint && paint->getImageFilter()) {
857         if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
858             if (justForImageFilter) {
859                 // early exit if the layer was just for the imageFilter
860                 return count;
861             }
862             SkPaint* p = lazyP.set(*paint);
863             p->setImageFilter(NULL);
864             paint = p;
865         }
866     }
867 
868     bool isOpaque;
869     SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
870 
871     SkDevice* device;
872     if (paint && paint->getImageFilter()) {
873         device = this->createCompatibleDevice(config, ir.width(), ir.height(),
874                                               isOpaque);
875     } else {
876         device = this->createLayerDevice(config, ir.width(), ir.height(),
877                                          isOpaque);
878     }
879     if (NULL == device) {
880         SkDebugf("Unable to create device for layer.");
881         return count;
882     }
883 
884     device->setOrigin(ir.fLeft, ir.fTop);
885     DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
886     device->unref();
887 
888     layer->fNext = fMCRec->fTopLayer;
889     fMCRec->fLayer = layer;
890     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
891 
892     fSaveLayerCount += 1;
893     return count;
894 }
895 
saveLayerAlpha(const SkRect * bounds,U8CPU alpha,SaveFlags flags)896 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
897                              SaveFlags flags) {
898     if (0xFF == alpha) {
899         return this->saveLayer(bounds, NULL, flags);
900     } else {
901         SkPaint tmpPaint;
902         tmpPaint.setAlpha(alpha);
903         return this->saveLayer(bounds, &tmpPaint, flags);
904     }
905 }
906 
restore()907 void SkCanvas::restore() {
908     // check for underflow
909     if (fMCStack.count() > 1) {
910         this->internalRestore();
911     }
912 }
913 
internalRestore()914 void SkCanvas::internalRestore() {
915     SkASSERT(fMCStack.count() != 0);
916 
917     fDeviceCMDirty = true;
918     fLocalBoundsCompareTypeDirty = true;
919 
920     fClipStack.restore();
921     // reserve our layer (if any)
922     DeviceCM* layer = fMCRec->fLayer;   // may be null
923     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
924     fMCRec->fLayer = NULL;
925 
926     // now do the normal restore()
927     fMCRec->~MCRec();       // balanced in save()
928     fMCStack.pop_back();
929     fMCRec = (MCRec*)fMCStack.back();
930 
931     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
932         since if we're being recorded, we don't want to record this (the
933         recorder will have already recorded the restore).
934     */
935     if (NULL != layer) {
936         if (layer->fNext) {
937             const SkIPoint& origin = layer->fDevice->getOrigin();
938             this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
939                                      layer->fPaint);
940             // reset this, since internalDrawDevice will have set it to true
941             fDeviceCMDirty = true;
942 
943             SkASSERT(fSaveLayerCount > 0);
944             fSaveLayerCount -= 1;
945         }
946         SkDELETE(layer);
947     }
948 
949     SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
950 }
951 
getSaveCount() const952 int SkCanvas::getSaveCount() const {
953     return fMCStack.count();
954 }
955 
restoreToCount(int count)956 void SkCanvas::restoreToCount(int count) {
957     // sanity check
958     if (count < 1) {
959         count = 1;
960     }
961 
962     int n = this->getSaveCount() - count;
963     for (int i = 0; i < n; ++i) {
964         this->restore();
965     }
966 }
967 
isDrawingToLayer() const968 bool SkCanvas::isDrawingToLayer() const {
969     return fSaveLayerCount > 0;
970 }
971 
972 /////////////////////////////////////////////////////////////////////////////
973 
974 // can't draw it if its empty, or its too big for a fixed-point width or height
reject_bitmap(const SkBitmap & bitmap)975 static bool reject_bitmap(const SkBitmap& bitmap) {
976     return  bitmap.width() <= 0 || bitmap.height() <= 0
977 #ifndef SK_ALLOW_OVER_32K_BITMAPS
978             || bitmap.width() > 32767 || bitmap.height() > 32767
979 #endif
980             ;
981 }
982 
internalDrawBitmap(const SkBitmap & bitmap,const SkIRect * srcRect,const SkMatrix & matrix,const SkPaint * paint)983 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
984                                 const SkMatrix& matrix, const SkPaint* paint) {
985     if (reject_bitmap(bitmap)) {
986         return;
987     }
988 
989     SkLazyPaint lazy;
990     if (NULL == paint) {
991         paint = lazy.init();
992     }
993     this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
994 }
995 
internalDrawDevice(SkDevice * srcDev,int x,int y,const SkPaint * paint)996 void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y,
997                                   const SkPaint* paint) {
998     SkPaint tmp;
999     if (NULL == paint) {
1000         tmp.setDither(true);
1001         paint = &tmp;
1002     }
1003 
1004     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1005     while (iter.next()) {
1006         SkDevice* dstDev = iter.fDevice;
1007         paint = &looper.paint();
1008         SkImageFilter* filter = paint->getImageFilter();
1009         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1010         if (filter && !dstDev->canHandleImageFilter(filter)) {
1011             SkDeviceImageFilterProxy proxy(dstDev);
1012             SkBitmap dst;
1013             const SkBitmap& src = srcDev->accessBitmap(false);
1014             if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
1015                 SkPaint tmpUnfiltered(*paint);
1016                 tmpUnfiltered.setImageFilter(NULL);
1017                 dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered);
1018             }
1019         } else {
1020             dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1021         }
1022     }
1023     LOOPER_END
1024 }
1025 
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint * paint)1026 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1027                           const SkPaint* paint) {
1028     SkDEBUGCODE(bitmap.validate();)
1029     CHECK_LOCKCOUNT_BALANCE(bitmap);
1030 
1031     if (reject_bitmap(bitmap)) {
1032         return;
1033     }
1034 
1035     SkPaint tmp;
1036     if (NULL == paint) {
1037         paint = &tmp;
1038     }
1039 
1040     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1041 
1042     while (iter.next()) {
1043         paint = &looper.paint();
1044         SkImageFilter* filter = paint->getImageFilter();
1045         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1046         if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1047             SkDeviceImageFilterProxy proxy(iter.fDevice);
1048             SkBitmap dst;
1049             if (filter->filterImage(&proxy, bitmap, *iter.fMatrix,
1050                                     &dst, &pos)) {
1051                 SkPaint tmpUnfiltered(*paint);
1052                 tmpUnfiltered.setImageFilter(NULL);
1053                 iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(),
1054                                          tmpUnfiltered);
1055             }
1056         } else {
1057             iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1058         }
1059     }
1060     LOOPER_END
1061 }
1062 
1063 /////////////////////////////////////////////////////////////////////////////
1064 
translate(SkScalar dx,SkScalar dy)1065 bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
1066     fDeviceCMDirty = true;
1067     fLocalBoundsCompareTypeDirty = true;
1068     return fMCRec->fMatrix->preTranslate(dx, dy);
1069 }
1070 
scale(SkScalar sx,SkScalar sy)1071 bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
1072     fDeviceCMDirty = true;
1073     fLocalBoundsCompareTypeDirty = true;
1074     return fMCRec->fMatrix->preScale(sx, sy);
1075 }
1076 
rotate(SkScalar degrees)1077 bool SkCanvas::rotate(SkScalar degrees) {
1078     fDeviceCMDirty = true;
1079     fLocalBoundsCompareTypeDirty = true;
1080     return fMCRec->fMatrix->preRotate(degrees);
1081 }
1082 
skew(SkScalar sx,SkScalar sy)1083 bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
1084     fDeviceCMDirty = true;
1085     fLocalBoundsCompareTypeDirty = true;
1086     return fMCRec->fMatrix->preSkew(sx, sy);
1087 }
1088 
concat(const SkMatrix & matrix)1089 bool SkCanvas::concat(const SkMatrix& matrix) {
1090     fDeviceCMDirty = true;
1091     fLocalBoundsCompareTypeDirty = true;
1092     return fMCRec->fMatrix->preConcat(matrix);
1093 }
1094 
setMatrix(const SkMatrix & matrix)1095 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1096     fDeviceCMDirty = true;
1097     fLocalBoundsCompareTypeDirty = true;
1098     *fMCRec->fMatrix = matrix;
1099 }
1100 
1101 // this is not virtual, so it must call a virtual method so that subclasses
1102 // will see its action
resetMatrix()1103 void SkCanvas::resetMatrix() {
1104     SkMatrix matrix;
1105 
1106     matrix.reset();
1107     this->setMatrix(matrix);
1108 }
1109 
1110 //////////////////////////////////////////////////////////////////////////////
1111 
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)1112 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1113 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1114     if (SkRegion::kIntersect_Op == op) {
1115         if (fMCRec->fRasterClip->isEmpty()) {
1116             return false;
1117         }
1118 
1119         if (this->quickReject(rect)) {
1120             fDeviceCMDirty = true;
1121             fLocalBoundsCompareTypeDirty = true;
1122 
1123             fClipStack.clipEmpty();
1124             return fMCRec->fRasterClip->setEmpty();
1125         }
1126     }
1127 #endif
1128 
1129     AutoValidateClip avc(this);
1130 
1131     fDeviceCMDirty = true;
1132     fLocalBoundsCompareTypeDirty = true;
1133     doAA &= fAllowSoftClip;
1134 
1135     if (fMCRec->fMatrix->rectStaysRect()) {
1136         // for these simpler matrices, we can stay a rect ever after applying
1137         // the matrix. This means we don't have to a) make a path, and b) tell
1138         // the region code to scan-convert the path, only to discover that it
1139         // is really just a rect.
1140         SkRect      r;
1141 
1142         fMCRec->fMatrix->mapRect(&r, rect);
1143         fClipStack.clipDevRect(r, op, doAA);
1144         return fMCRec->fRasterClip->op(r, op, doAA);
1145     } else {
1146         // since we're rotate or some such thing, we convert the rect to a path
1147         // and clip against that, since it can handle any matrix. However, to
1148         // avoid recursion in the case where we are subclassed (e.g. Pictures)
1149         // we explicitly call "our" version of clipPath.
1150         SkPath  path;
1151 
1152         path.addRect(rect);
1153         return this->SkCanvas::clipPath(path, op, doAA);
1154     }
1155 }
1156 
clipPathHelper(const SkCanvas * canvas,SkRasterClip * currClip,const SkPath & devPath,SkRegion::Op op,bool doAA)1157 static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
1158                            const SkPath& devPath, SkRegion::Op op, bool doAA) {
1159     // base is used to limit the size (and therefore memory allocation) of the
1160     // region that results from scan converting devPath.
1161     SkRegion base;
1162 
1163     if (SkRegion::kIntersect_Op == op) {
1164         // since we are intersect, we can do better (tighter) with currRgn's
1165         // bounds, than just using the device. However, if currRgn is complex,
1166         // our region blitter may hork, so we do that case in two steps.
1167         if (currClip->isRect()) {
1168             return currClip->setPath(devPath, *currClip, doAA);
1169         } else {
1170             base.setRect(currClip->getBounds());
1171             SkRasterClip clip;
1172             clip.setPath(devPath, base, doAA);
1173             return currClip->op(clip, op);
1174         }
1175     } else {
1176         const SkDevice* device = canvas->getDevice();
1177         if (!device) {
1178             return currClip->setEmpty();
1179         }
1180 
1181         base.setRect(0, 0, device->width(), device->height());
1182 
1183         if (SkRegion::kReplace_Op == op) {
1184             return currClip->setPath(devPath, base, doAA);
1185         } else {
1186             SkRasterClip clip;
1187             clip.setPath(devPath, base, doAA);
1188             return currClip->op(clip, op);
1189         }
1190     }
1191 }
1192 
clipRRect(const SkRRect & rrect,SkRegion::Op op,bool doAA)1193 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1194     if (rrect.isRect()) {
1195         // call the non-virtual version
1196         return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA);
1197     } else {
1198         SkPath path;
1199         path.addRRect(rrect);
1200         // call the non-virtual version
1201         return this->SkCanvas::clipPath(path, op, doAA);
1202     }
1203 }
1204 
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)1205 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1206 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1207     if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1208         if (fMCRec->fRasterClip->isEmpty()) {
1209             return false;
1210         }
1211 
1212         if (this->quickReject(path.getBounds())) {
1213             fDeviceCMDirty = true;
1214             fLocalBoundsCompareTypeDirty = true;
1215 
1216             fClipStack.clipEmpty();
1217             return fMCRec->fRasterClip->setEmpty();
1218         }
1219     }
1220 #endif
1221 
1222     AutoValidateClip avc(this);
1223 
1224     fDeviceCMDirty = true;
1225     fLocalBoundsCompareTypeDirty = true;
1226     doAA &= fAllowSoftClip;
1227 
1228     SkPath devPath;
1229     path.transform(*fMCRec->fMatrix, &devPath);
1230 
1231     // Check if the transfomation, or the original path itself
1232     // made us empty. Note this can also happen if we contained NaN
1233     // values. computing the bounds detects this, and will set our
1234     // bounds to empty if that is the case. (see SkRect::set(pts, count))
1235     if (devPath.getBounds().isEmpty()) {
1236         // resetting the path will remove any NaN or other wanky values
1237         // that might upset our scan converter.
1238         devPath.reset();
1239     }
1240 
1241     // if we called path.swap() we could avoid a deep copy of this path
1242     fClipStack.clipDevPath(devPath, op, doAA);
1243 
1244     return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
1245 }
1246 
clipRegion(const SkRegion & rgn,SkRegion::Op op)1247 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1248     AutoValidateClip avc(this);
1249 
1250     fDeviceCMDirty = true;
1251     fLocalBoundsCompareTypeDirty = true;
1252 
1253     // todo: signal fClipStack that we have a region, and therefore (I guess)
1254     // we have to ignore it, and use the region directly?
1255     fClipStack.clipDevRect(rgn.getBounds(), op);
1256 
1257     return fMCRec->fRasterClip->op(rgn, op);
1258 }
1259 
1260 #ifdef SK_DEBUG
validateClip() const1261 void SkCanvas::validateClip() const {
1262     // construct clipRgn from the clipstack
1263     const SkDevice* device = this->getDevice();
1264     if (!device) {
1265         SkASSERT(this->getTotalClip().isEmpty());
1266         return;
1267     }
1268 
1269     SkIRect ir;
1270     ir.set(0, 0, device->width(), device->height());
1271     SkRasterClip tmpClip(ir);
1272 
1273     SkClipStack::B2TIter                iter(fClipStack);
1274     const SkClipStack::Element* element;
1275     while ((element = iter.next()) != NULL) {
1276         switch (element->getType()) {
1277             case SkClipStack::Element::kPath_Type:
1278                 clipPathHelper(this,
1279                                &tmpClip,
1280                                element->getPath(),
1281                                element->getOp(),
1282                                element->isAA());
1283                 break;
1284             case SkClipStack::Element::kRect_Type:
1285                 element->getRect().round(&ir);
1286                 tmpClip.op(ir, element->getOp());
1287                 break;
1288             case SkClipStack::Element::kEmpty_Type:
1289                 tmpClip.setEmpty();
1290                 break;
1291         }
1292     }
1293 
1294 #if 0   // enable this locally for testing
1295     // now compare against the current rgn
1296     const SkRegion& rgn = this->getTotalClip();
1297     SkASSERT(rgn == tmpClip);
1298 #endif
1299 }
1300 #endif
1301 
replayClips(ClipVisitor * visitor) const1302 void SkCanvas::replayClips(ClipVisitor* visitor) const {
1303     SkClipStack::B2TIter                iter(fClipStack);
1304     const SkClipStack::Element*         element;
1305 
1306     static const SkRect kEmpty = { 0, 0, 0, 0 };
1307     while ((element = iter.next()) != NULL) {
1308         switch (element->getType()) {
1309             case SkClipStack::Element::kPath_Type:
1310                 visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
1311                 break;
1312             case SkClipStack::Element::kRect_Type:
1313                 visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
1314                 break;
1315             case SkClipStack::Element::kEmpty_Type:
1316                 visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
1317                 break;
1318         }
1319     }
1320 }
1321 
1322 ///////////////////////////////////////////////////////////////////////////////
1323 
computeLocalClipBoundsCompareType() const1324 void SkCanvas::computeLocalClipBoundsCompareType() const {
1325     SkRect r;
1326 
1327     if (!this->getClipBounds(&r)) {
1328         fLocalBoundsCompareType.setEmpty();
1329     } else {
1330         fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft),
1331                                     SkScalarToCompareType(r.fTop),
1332                                     SkScalarToCompareType(r.fRight),
1333                                     SkScalarToCompareType(r.fBottom));
1334     }
1335 }
1336 
quickReject(const SkRect & rect) const1337 bool SkCanvas::quickReject(const SkRect& rect) const {
1338 
1339     if (!rect.isFinite())
1340         return true;
1341 
1342     if (fMCRec->fRasterClip->isEmpty()) {
1343         return true;
1344     }
1345 
1346     if (fMCRec->fMatrix->hasPerspective()) {
1347         SkRect dst;
1348         fMCRec->fMatrix->mapRect(&dst, rect);
1349         SkIRect idst;
1350         dst.roundOut(&idst);
1351         return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1352     } else {
1353         const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
1354 
1355         // for speed, do the most likely reject compares first
1356         SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
1357         SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
1358         if (userT >= clipR.fBottom || userB <= clipR.fTop) {
1359             return true;
1360         }
1361         SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
1362         SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
1363         if (userL >= clipR.fRight || userR <= clipR.fLeft) {
1364             return true;
1365         }
1366         return false;
1367     }
1368 }
1369 
quickReject(const SkPath & path) const1370 bool SkCanvas::quickReject(const SkPath& path) const {
1371     return path.isEmpty() || this->quickReject(path.getBounds());
1372 }
1373 
pinIntForScalar(int x)1374 static inline int pinIntForScalar(int x) {
1375 #ifdef SK_SCALAR_IS_FIXED
1376     if (x < SK_MinS16) {
1377         x = SK_MinS16;
1378     } else if (x > SK_MaxS16) {
1379         x = SK_MaxS16;
1380     }
1381 #endif
1382     return x;
1383 }
1384 
getClipBounds(SkRect * bounds) const1385 bool SkCanvas::getClipBounds(SkRect* bounds) const {
1386     SkIRect ibounds;
1387     if (!getClipDeviceBounds(&ibounds)) {
1388         return false;
1389     }
1390 
1391     SkMatrix inverse;
1392     // if we can't invert the CTM, we can't return local clip bounds
1393     if (!fMCRec->fMatrix->invert(&inverse)) {
1394         if (bounds) {
1395             bounds->setEmpty();
1396         }
1397         return false;
1398     }
1399 
1400     if (NULL != bounds) {
1401         SkRect r;
1402         // adjust it outwards in case we are antialiasing
1403         const int inset = 1;
1404 
1405         // SkRect::iset() will correctly assert if we pass a value out of range
1406         // (when SkScalar==fixed), so we pin to legal values. This does not
1407         // really returnt the correct answer, but its the best we can do given
1408         // that we've promised to return SkRect (even though we support devices
1409         // that can be larger than 32K in width or height).
1410         r.iset(pinIntForScalar(ibounds.fLeft - inset),
1411                pinIntForScalar(ibounds.fTop - inset),
1412                pinIntForScalar(ibounds.fRight + inset),
1413                pinIntForScalar(ibounds.fBottom + inset));
1414         inverse.mapRect(bounds, r);
1415     }
1416     return true;
1417 }
1418 
getClipDeviceBounds(SkIRect * bounds) const1419 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1420     const SkRasterClip& clip = *fMCRec->fRasterClip;
1421     if (clip.isEmpty()) {
1422         if (bounds) {
1423             bounds->setEmpty();
1424         }
1425         return false;
1426     }
1427 
1428     if (NULL != bounds) {
1429         *bounds = clip.getBounds();
1430     }
1431     return true;
1432 }
1433 
getTotalMatrix() const1434 const SkMatrix& SkCanvas::getTotalMatrix() const {
1435     return *fMCRec->fMatrix;
1436 }
1437 
getClipType() const1438 SkCanvas::ClipType SkCanvas::getClipType() const {
1439     if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
1440     if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
1441     return kComplex_ClipType;
1442 }
1443 
getTotalClip() const1444 const SkRegion& SkCanvas::getTotalClip() const {
1445     return fMCRec->fRasterClip->forceGetBW();
1446 }
1447 
createLayerDevice(SkBitmap::Config config,int width,int height,bool isOpaque)1448 SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
1449                                       int width, int height,
1450                                       bool isOpaque) {
1451     SkDevice* device = this->getTopDevice();
1452     if (device) {
1453         return device->createCompatibleDeviceForSaveLayer(config, width, height,
1454                                                           isOpaque);
1455     } else {
1456         return NULL;
1457     }
1458 }
1459 
createCompatibleDevice(SkBitmap::Config config,int width,int height,bool isOpaque)1460 SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
1461                                            int width, int height,
1462                                            bool isOpaque) {
1463     SkDevice* device = this->getDevice();
1464     if (device) {
1465         return device->createCompatibleDevice(config, width, height, isOpaque);
1466     } else {
1467         return NULL;
1468     }
1469 }
1470 
1471 
1472 //////////////////////////////////////////////////////////////////////////////
1473 //  These are the virtual drawing methods
1474 //////////////////////////////////////////////////////////////////////////////
1475 
clear(SkColor color)1476 void SkCanvas::clear(SkColor color) {
1477     SkDrawIter  iter(this);
1478 
1479     while (iter.next()) {
1480         iter.fDevice->clear(color);
1481     }
1482 }
1483 
drawPaint(const SkPaint & paint)1484 void SkCanvas::drawPaint(const SkPaint& paint) {
1485     this->internalDrawPaint(paint);
1486 }
1487 
internalDrawPaint(const SkPaint & paint)1488 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1489     CHECK_SHADER_NOSETCONTEXT(paint);
1490 
1491     LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
1492 
1493     while (iter.next()) {
1494         iter.fDevice->drawPaint(iter, looper.paint());
1495     }
1496 
1497     LOOPER_END
1498 }
1499 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1500 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1501                           const SkPaint& paint) {
1502     if ((long)count <= 0) {
1503         return;
1504     }
1505 
1506     CHECK_SHADER_NOSETCONTEXT(paint);
1507 
1508     if (paint.canComputeFastBounds()) {
1509         SkRect r;
1510         // special-case 2 points (common for drawing a single line)
1511         if (2 == count) {
1512             r.set(pts[0], pts[1]);
1513         } else {
1514             r.set(pts, count);
1515         }
1516         SkRect storage;
1517         if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
1518             return;
1519         }
1520     }
1521 
1522     SkASSERT(pts != NULL);
1523 
1524     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1525 
1526     while (iter.next()) {
1527         iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1528     }
1529 
1530     LOOPER_END
1531 }
1532 
drawRect(const SkRect & r,const SkPaint & paint)1533 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1534     CHECK_SHADER_NOSETCONTEXT(paint);
1535 
1536     if (paint.canComputeFastBounds()) {
1537         SkRect storage;
1538         if (this->quickReject(paint.computeFastBounds(r, &storage))) {
1539             return;
1540         }
1541     }
1542 
1543     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
1544 
1545     while (iter.next()) {
1546         iter.fDevice->drawRect(iter, r, looper.paint());
1547     }
1548 
1549     LOOPER_END
1550 }
1551 
drawOval(const SkRect & oval,const SkPaint & paint)1552 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1553     CHECK_SHADER_NOSETCONTEXT(paint);
1554 
1555     if (paint.canComputeFastBounds()) {
1556         SkRect storage;
1557         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
1558             return;
1559         }
1560     }
1561 
1562     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type)
1563 
1564     while (iter.next()) {
1565         iter.fDevice->drawOval(iter, oval, looper.paint());
1566     }
1567 
1568     LOOPER_END
1569 }
1570 
drawRRect(const SkRRect & rrect,const SkPaint & paint)1571 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1572     CHECK_SHADER_NOSETCONTEXT(paint);
1573 
1574     if (paint.canComputeFastBounds()) {
1575         SkRect storage;
1576         if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
1577             return;
1578         }
1579     }
1580 
1581     if (rrect.isRect()) {
1582         // call the non-virtual version
1583         this->SkCanvas::drawRect(rrect.getBounds(), paint);
1584     } else {
1585         SkPath  path;
1586         path.addRRect(rrect);
1587         // call the non-virtual version
1588         this->SkCanvas::drawPath(path, paint);
1589     }
1590 }
1591 
1592 
drawPath(const SkPath & path,const SkPaint & paint)1593 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1594     CHECK_SHADER_NOSETCONTEXT(paint);
1595 
1596     if (!path.isFinite()) {
1597         return;
1598     }
1599 
1600     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1601         SkRect storage;
1602         const SkRect& bounds = path.getBounds();
1603         if (this->quickReject(paint.computeFastBounds(bounds, &storage))) {
1604             return;
1605         }
1606     }
1607     if (path.isEmpty()) {
1608         if (path.isInverseFillType()) {
1609             this->internalDrawPaint(paint);
1610         }
1611         return;
1612     }
1613 
1614     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1615 
1616     while (iter.next()) {
1617         iter.fDevice->drawPath(iter, path, looper.paint());
1618     }
1619 
1620     LOOPER_END
1621 }
1622 
drawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)1623 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1624                           const SkPaint* paint) {
1625     SkDEBUGCODE(bitmap.validate();)
1626 
1627     if (NULL == paint || paint->canComputeFastBounds()) {
1628         SkRect bounds = {
1629             x, y,
1630             x + SkIntToScalar(bitmap.width()),
1631             y + SkIntToScalar(bitmap.height())
1632         };
1633         if (paint) {
1634             (void)paint->computeFastBounds(bounds, &bounds);
1635         }
1636         if (this->quickReject(bounds)) {
1637             return;
1638         }
1639     }
1640 
1641     SkMatrix matrix;
1642     matrix.setTranslate(x, y);
1643     this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1644 }
1645 
1646 // 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)1647 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1648                                       const SkRect& dst, const SkPaint* paint) {
1649     if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1650         return;
1651     }
1652 
1653     CHECK_LOCKCOUNT_BALANCE(bitmap);
1654 
1655     if (NULL == paint || paint->canComputeFastBounds()) {
1656         SkRect storage;
1657         const SkRect* bounds = &dst;
1658         if (paint) {
1659             bounds = &paint->computeFastBounds(dst, &storage);
1660         }
1661         if (this->quickReject(*bounds)) {
1662             return;
1663         }
1664     }
1665 
1666     SkLazyPaint lazy;
1667     if (NULL == paint) {
1668         paint = lazy.init();
1669     }
1670 
1671     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1672 
1673     while (iter.next()) {
1674         iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint());
1675     }
1676 
1677     LOOPER_END
1678 }
1679 
drawBitmapRectToRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint)1680 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1681                                     const SkRect& dst, const SkPaint* paint) {
1682     SkDEBUGCODE(bitmap.validate();)
1683     this->internalDrawBitmapRect(bitmap, src, dst, paint);
1684 }
1685 
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)1686 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1687                                 const SkPaint* paint) {
1688     SkDEBUGCODE(bitmap.validate();)
1689     this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1690 }
1691 
commonDrawBitmap(const SkBitmap & bitmap,const SkIRect * srcRect,const SkMatrix & matrix,const SkPaint & paint)1692 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
1693                                 const SkMatrix& matrix, const SkPaint& paint) {
1694     SkDEBUGCODE(bitmap.validate();)
1695     CHECK_LOCKCOUNT_BALANCE(bitmap);
1696 
1697     LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1698 
1699     while (iter.next()) {
1700         iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
1701     }
1702 
1703     LOOPER_END
1704 }
1705 
internalDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1706 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1707                                       const SkIRect& center, const SkRect& dst,
1708                                       const SkPaint* paint) {
1709     if (NULL == paint || paint->canComputeFastBounds()) {
1710         SkRect storage;
1711         const SkRect* bounds = &dst;
1712         if (paint) {
1713             bounds = &paint->computeFastBounds(dst, &storage);
1714         }
1715         if (this->quickReject(*bounds)) {
1716             return;
1717         }
1718     }
1719 
1720     const int32_t w = bitmap.width();
1721     const int32_t h = bitmap.height();
1722 
1723     SkIRect c = center;
1724     // pin center to the bounds of the bitmap
1725     c.fLeft = SkMax32(0, center.fLeft);
1726     c.fTop = SkMax32(0, center.fTop);
1727     c.fRight = SkPin32(center.fRight, c.fLeft, w);
1728     c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1729 
1730     const SkScalar srcX[4] = {
1731         0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
1732     };
1733     const SkScalar srcY[4] = {
1734         0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
1735     };
1736     SkScalar dstX[4] = {
1737         dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1738         dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1739     };
1740     SkScalar dstY[4] = {
1741         dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1742         dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1743     };
1744 
1745     if (dstX[1] > dstX[2]) {
1746         dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1747         dstX[2] = dstX[1];
1748     }
1749 
1750     if (dstY[1] > dstY[2]) {
1751         dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1752         dstY[2] = dstY[1];
1753     }
1754 
1755     for (int y = 0; y < 3; y++) {
1756         SkRect s, d;
1757 
1758         s.fTop = srcY[y];
1759         s.fBottom = srcY[y+1];
1760         d.fTop = dstY[y];
1761         d.fBottom = dstY[y+1];
1762         for (int x = 0; x < 3; x++) {
1763             s.fLeft = srcX[x];
1764             s.fRight = srcX[x+1];
1765             d.fLeft = dstX[x];
1766             d.fRight = dstX[x+1];
1767             this->internalDrawBitmapRect(bitmap, &s, d, paint);
1768         }
1769     }
1770 }
1771 
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1772 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1773                               const SkRect& dst, const SkPaint* paint) {
1774     SkDEBUGCODE(bitmap.validate();)
1775 
1776     // Need a device entry-point, so gpu can use a mesh
1777     this->internalDrawBitmapNine(bitmap, center, dst, paint);
1778 }
1779 
1780 class SkDeviceFilteredPaint {
1781 public:
SkDeviceFilteredPaint(SkDevice * device,const SkPaint & paint)1782     SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
1783         SkDevice::TextFlags flags;
1784         if (device->filterTextFlags(paint, &flags)) {
1785             SkPaint* newPaint = fLazy.set(paint);
1786             newPaint->setFlags(flags.fFlags);
1787             newPaint->setHinting(flags.fHinting);
1788             fPaint = newPaint;
1789         } else {
1790             fPaint = &paint;
1791         }
1792     }
1793 
paint() const1794     const SkPaint& paint() const { return *fPaint; }
1795 
1796 private:
1797     const SkPaint*  fPaint;
1798     SkLazyPaint     fLazy;
1799 };
1800 
DrawRect(const SkDraw & draw,const SkPaint & paint,const SkRect & r,SkScalar textSize)1801 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
1802                         const SkRect& r, SkScalar textSize) {
1803     if (paint.getStyle() == SkPaint::kFill_Style) {
1804         draw.fDevice->drawRect(draw, r, paint);
1805     } else {
1806         SkPaint p(paint);
1807         p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1808         draw.fDevice->drawRect(draw, r, p);
1809     }
1810 }
1811 
DrawTextDecorations(const SkDraw & draw,const SkPaint & paint,const char text[],size_t byteLength,SkScalar x,SkScalar y)1812 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1813                                    const char text[], size_t byteLength,
1814                                    SkScalar x, SkScalar y) {
1815     SkASSERT(byteLength == 0 || text != NULL);
1816 
1817     // nothing to draw
1818     if (text == NULL || byteLength == 0 ||
1819         draw.fClip->isEmpty() ||
1820         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1821         return;
1822     }
1823 
1824     SkScalar    width = 0;
1825     SkPoint     start;
1826 
1827     start.set(0, 0);    // to avoid warning
1828     if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1829                             SkPaint::kStrikeThruText_Flag)) {
1830         width = paint.measureText(text, byteLength);
1831 
1832         SkScalar offsetX = 0;
1833         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1834             offsetX = SkScalarHalf(width);
1835         } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1836             offsetX = width;
1837         }
1838         start.set(x - offsetX, y);
1839     }
1840 
1841     if (0 == width) {
1842         return;
1843     }
1844 
1845     uint32_t flags = paint.getFlags();
1846 
1847     if (flags & (SkPaint::kUnderlineText_Flag |
1848                  SkPaint::kStrikeThruText_Flag)) {
1849         SkScalar textSize = paint.getTextSize();
1850         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1851         SkRect   r;
1852 
1853         r.fLeft = start.fX;
1854         r.fRight = start.fX + width;
1855 
1856         if (flags & SkPaint::kUnderlineText_Flag) {
1857             SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1858                                              start.fY);
1859             r.fTop = offset;
1860             r.fBottom = offset + height;
1861             DrawRect(draw, paint, r, textSize);
1862         }
1863         if (flags & SkPaint::kStrikeThruText_Flag) {
1864             SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1865                                              start.fY);
1866             r.fTop = offset;
1867             r.fBottom = offset + height;
1868             DrawRect(draw, paint, r, textSize);
1869         }
1870     }
1871 }
1872 
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)1873 void SkCanvas::drawText(const void* text, size_t byteLength,
1874                         SkScalar x, SkScalar y, const SkPaint& paint) {
1875     CHECK_SHADER_NOSETCONTEXT(paint);
1876 
1877     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1878 
1879     while (iter.next()) {
1880         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1881         iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
1882         DrawTextDecorations(iter, dfp.paint(),
1883                             static_cast<const char*>(text), byteLength, x, y);
1884     }
1885 
1886     LOOPER_END
1887 }
1888 
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)1889 void SkCanvas::drawPosText(const void* text, size_t byteLength,
1890                            const SkPoint pos[], const SkPaint& paint) {
1891     CHECK_SHADER_NOSETCONTEXT(paint);
1892 
1893     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1894 
1895     while (iter.next()) {
1896         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1897         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1898                                   dfp.paint());
1899     }
1900 
1901     LOOPER_END
1902 }
1903 
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)1904 void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1905                             const SkScalar xpos[], SkScalar constY,
1906                             const SkPaint& paint) {
1907     CHECK_SHADER_NOSETCONTEXT(paint);
1908 
1909     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1910 
1911     while (iter.next()) {
1912         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1913         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1914                                   dfp.paint());
1915     }
1916 
1917     LOOPER_END
1918 }
1919 
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)1920 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1921                               const SkPath& path, const SkMatrix* matrix,
1922                               const SkPaint& paint) {
1923     CHECK_SHADER_NOSETCONTEXT(paint);
1924 
1925     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1926 
1927     while (iter.next()) {
1928         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1929                                      matrix, looper.paint());
1930     }
1931 
1932     LOOPER_END
1933 }
1934 
1935 #ifdef SK_BUILD_FOR_ANDROID
drawPosTextOnPath(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint,const SkPath & path,const SkMatrix * matrix)1936 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
1937                                  const SkPoint pos[], const SkPaint& paint,
1938                                  const SkPath& path, const SkMatrix* matrix) {
1939     CHECK_SHADER_NOSETCONTEXT(paint);
1940 
1941     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1942 
1943     while (iter.next()) {
1944         iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
1945                                         looper.paint(), path, matrix);
1946     }
1947 
1948     LOOPER_END
1949 }
1950 #endif
1951 
drawVertices(VertexMode vmode,int vertexCount,const SkPoint verts[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)1952 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1953                             const SkPoint verts[], const SkPoint texs[],
1954                             const SkColor colors[], SkXfermode* xmode,
1955                             const uint16_t indices[], int indexCount,
1956                             const SkPaint& paint) {
1957     CHECK_SHADER_NOSETCONTEXT(paint);
1958 
1959     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1960 
1961     while (iter.next()) {
1962         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1963                                    colors, xmode, indices, indexCount,
1964                                    looper.paint());
1965     }
1966 
1967     LOOPER_END
1968 }
1969 
drawData(const void * data,size_t length)1970 void SkCanvas::drawData(const void* data, size_t length) {
1971     // do nothing. Subclasses may do something with the data
1972 }
1973 
1974 //////////////////////////////////////////////////////////////////////////////
1975 // These methods are NOT virtual, and therefore must call back into virtual
1976 // methods, rather than actually drawing themselves.
1977 //////////////////////////////////////////////////////////////////////////////
1978 
drawARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b,SkXfermode::Mode mode)1979 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1980                         SkXfermode::Mode mode) {
1981     SkPaint paint;
1982 
1983     paint.setARGB(a, r, g, b);
1984     if (SkXfermode::kSrcOver_Mode != mode) {
1985         paint.setXfermodeMode(mode);
1986     }
1987     this->drawPaint(paint);
1988 }
1989 
drawColor(SkColor c,SkXfermode::Mode mode)1990 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
1991     SkPaint paint;
1992 
1993     paint.setColor(c);
1994     if (SkXfermode::kSrcOver_Mode != mode) {
1995         paint.setXfermodeMode(mode);
1996     }
1997     this->drawPaint(paint);
1998 }
1999 
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)2000 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2001     SkPoint pt;
2002 
2003     pt.set(x, y);
2004     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2005 }
2006 
drawPoint(SkScalar x,SkScalar y,SkColor color)2007 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2008     SkPoint pt;
2009     SkPaint paint;
2010 
2011     pt.set(x, y);
2012     paint.setColor(color);
2013     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2014 }
2015 
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)2016 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2017                         const SkPaint& paint) {
2018     SkPoint pts[2];
2019 
2020     pts[0].set(x0, y0);
2021     pts[1].set(x1, y1);
2022     this->drawPoints(kLines_PointMode, 2, pts, paint);
2023 }
2024 
drawRectCoords(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom,const SkPaint & paint)2025 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2026                               SkScalar right, SkScalar bottom,
2027                               const SkPaint& paint) {
2028     SkRect  r;
2029 
2030     r.set(left, top, right, bottom);
2031     this->drawRect(r, paint);
2032 }
2033 
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)2034 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2035                           const SkPaint& paint) {
2036     if (radius < 0) {
2037         radius = 0;
2038     }
2039 
2040     SkRect  r;
2041     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2042     this->drawOval(r, paint);
2043 }
2044 
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)2045 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2046                              const SkPaint& paint) {
2047     if (rx > 0 && ry > 0) {
2048         if (paint.canComputeFastBounds()) {
2049             SkRect storage;
2050             if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2051                 return;
2052             }
2053         }
2054         SkRRect rrect;
2055         rrect.setRectXY(r, rx, ry);
2056         this->drawRRect(rrect, paint);
2057     } else {
2058         this->drawRect(r, paint);
2059     }
2060 }
2061 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2062 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2063                        SkScalar sweepAngle, bool useCenter,
2064                        const SkPaint& paint) {
2065     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2066         this->drawOval(oval, paint);
2067     } else {
2068         SkPath  path;
2069         if (useCenter) {
2070             path.moveTo(oval.centerX(), oval.centerY());
2071         }
2072         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2073         if (useCenter) {
2074             path.close();
2075         }
2076         this->drawPath(path, paint);
2077     }
2078 }
2079 
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)2080 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2081                                 const SkPath& path, SkScalar hOffset,
2082                                 SkScalar vOffset, const SkPaint& paint) {
2083     SkMatrix    matrix;
2084 
2085     matrix.setTranslate(hOffset, vOffset);
2086     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2087 }
2088 
2089 ///////////////////////////////////////////////////////////////////////////////
2090 
drawPicture(SkPicture & picture)2091 void SkCanvas::drawPicture(SkPicture& picture) {
2092     picture.draw(this);
2093 }
2094 
2095 ///////////////////////////////////////////////////////////////////////////////
2096 ///////////////////////////////////////////////////////////////////////////////
2097 
LayerIter(SkCanvas * canvas,bool skipEmptyClips)2098 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2099     SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2100 
2101     SkASSERT(canvas);
2102 
2103     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2104     fDone = !fImpl->next();
2105 }
2106 
~LayerIter()2107 SkCanvas::LayerIter::~LayerIter() {
2108     fImpl->~SkDrawIter();
2109 }
2110 
next()2111 void SkCanvas::LayerIter::next() {
2112     fDone = !fImpl->next();
2113 }
2114 
device() const2115 SkDevice* SkCanvas::LayerIter::device() const {
2116     return fImpl->getDevice();
2117 }
2118 
matrix() const2119 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2120     return fImpl->getMatrix();
2121 }
2122 
paint() const2123 const SkPaint& SkCanvas::LayerIter::paint() const {
2124     const SkPaint* paint = fImpl->getPaint();
2125     if (NULL == paint) {
2126         paint = &fDefaultPaint;
2127     }
2128     return *paint;
2129 }
2130 
clip() const2131 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
x() const2132 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const2133 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2134 
2135 ///////////////////////////////////////////////////////////////////////////////
2136 
~ClipVisitor()2137 SkCanvas::ClipVisitor::~ClipVisitor() { }
2138