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