• 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     this->init(NULL);
429 }
430 
SkCanvas(SkDevice * device)431 SkCanvas::SkCanvas(SkDevice* device)
432         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
433     inc_canvas();
434 
435     this->init(device);
436 }
437 
SkCanvas(const SkBitmap & bitmap)438 SkCanvas::SkCanvas(const SkBitmap& bitmap)
439         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
440     inc_canvas();
441 
442     this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
443 }
444 
~SkCanvas()445 SkCanvas::~SkCanvas() {
446     // free up the contents of our deque
447     this->restoreToCount(1);    // restore everything but the last
448     SkASSERT(0 == fLayerCount);
449 
450     this->internalRestore();    // restore the last, since we're going away
451 
452     SkSafeUnref(fBounder);
453 
454     dec_canvas();
455 }
456 
setBounder(SkBounder * bounder)457 SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
458     SkRefCnt_SafeAssign(fBounder, bounder);
459     return bounder;
460 }
461 
getDrawFilter() const462 SkDrawFilter* SkCanvas::getDrawFilter() const {
463     return fMCRec->fFilter;
464 }
465 
setDrawFilter(SkDrawFilter * filter)466 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
467     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
468     return filter;
469 }
470 
471 ///////////////////////////////////////////////////////////////////////////////
472 
flush()473 void SkCanvas::flush() {
474     SkDevice* device = this->getDevice();
475     if (device) {
476         device->flush();
477     }
478 }
479 
getDeviceSize() const480 SkISize SkCanvas::getDeviceSize() const {
481     SkDevice* d = this->getDevice();
482     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
483 }
484 
getDevice() const485 SkDevice* SkCanvas::getDevice() const {
486     // return root device
487     SkDeque::F2BIter iter(fMCStack);
488     MCRec*           rec = (MCRec*)iter.next();
489     SkASSERT(rec && rec->fLayer);
490     return rec->fLayer->fDevice;
491 }
492 
getTopDevice() const493 SkDevice* SkCanvas::getTopDevice() const {
494     return fMCRec->fTopLayer->fDevice;
495 }
496 
setDevice(SkDevice * device)497 SkDevice* SkCanvas::setDevice(SkDevice* device) {
498     // return root device
499     SkDeque::F2BIter iter(fMCStack);
500     MCRec*           rec = (MCRec*)iter.next();
501     SkASSERT(rec && rec->fLayer);
502     SkDevice*       rootDevice = rec->fLayer->fDevice;
503 
504     if (rootDevice == device) {
505         return device;
506     }
507 
508     /* Notify the devices that they are going in/out of scope, so they can do
509        things like lock/unlock their pixels, etc.
510     */
511     if (device) {
512         device->lockPixels();
513     }
514     if (rootDevice) {
515         rootDevice->unlockPixels();
516     }
517 
518     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
519     rootDevice = device;
520 
521     fDeviceCMDirty = true;
522 
523     /*  Now we update our initial region to have the bounds of the new device,
524         and then intersect all of the clips in our stack with these bounds,
525         to ensure that we can't draw outside of the device's bounds (and trash
526                                                                      memory).
527 
528     NOTE: this is only a partial-fix, since if the new device is larger than
529         the previous one, we don't know how to "enlarge" the clips in our stack,
530         so drawing may be artificially restricted. Without keeping a history of
531         all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
532         reconstruct the correct clips, so this approximation will have to do.
533         The caller really needs to restore() back to the base if they want to
534         accurately take advantage of the new device bounds.
535     */
536 
537     if (NULL == device) {
538         rec->fRasterClip->setEmpty();
539         while ((rec = (MCRec*)iter.next()) != NULL) {
540             (void)rec->fRasterClip->setEmpty();
541         }
542         fClipStack.reset();
543     } else {
544         // compute our total bounds for all devices
545         SkIRect bounds;
546 
547         bounds.set(0, 0, device->width(), device->height());
548 
549         // now jam our 1st clip to be bounds, and intersect the rest with that
550         rec->fRasterClip->setRect(bounds);
551         while ((rec = (MCRec*)iter.next()) != NULL) {
552             (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
553         }
554     }
555     return device;
556 }
557 
setBitmapDevice(const SkBitmap & bitmap)558 SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
559     SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
560     device->unref();
561     return device;
562 }
563 
readPixels(SkBitmap * bitmap,int x,int y,Config8888 config8888)564 bool SkCanvas::readPixels(SkBitmap* bitmap,
565                           int x, int y,
566                           Config8888 config8888) {
567     SkDevice* device = this->getDevice();
568     if (!device) {
569         return false;
570     }
571     return device->readPixels(bitmap, x, y, config8888);
572 }
573 
readPixels(const SkIRect & srcRect,SkBitmap * bitmap)574 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
575     SkDevice* device = this->getDevice();
576     if (!device) {
577         return false;
578     }
579 
580     SkIRect bounds;
581     bounds.set(0, 0, device->width(), device->height());
582     if (!bounds.intersect(srcRect)) {
583         return false;
584     }
585 
586     SkBitmap tmp;
587     tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
588                                                bounds.height());
589     if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
590         bitmap->swap(tmp);
591         return true;
592     } else {
593         return false;
594     }
595 }
596 
writePixels(const SkBitmap & bitmap,int x,int y,Config8888 config8888)597 void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y,
598                            Config8888 config8888) {
599     SkDevice* device = this->getDevice();
600     if (device) {
601         device->writePixels(bitmap, x, y, config8888);
602     }
603 }
604 
canvasForDrawIter()605 SkCanvas* SkCanvas::canvasForDrawIter() {
606     return this;
607 }
608 
609 //////////////////////////////////////////////////////////////////////////////
610 
updateDeviceCMCache()611 void SkCanvas::updateDeviceCMCache() {
612     if (fDeviceCMDirty) {
613         const SkMatrix& totalMatrix = this->getTotalMatrix();
614         const SkRasterClip& totalClip = *fMCRec->fRasterClip;
615         DeviceCM*       layer = fMCRec->fTopLayer;
616 
617         if (NULL == layer->fNext) {   // only one layer
618             layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
619             if (fUseExternalMatrix) {
620                 layer->updateExternalMatrix(fExternalMatrix,
621                                             fExternalInverse);
622             }
623         } else {
624             SkRasterClip clip(totalClip);
625             do {
626                 layer->updateMC(totalMatrix, clip, fClipStack, &clip);
627                 if (fUseExternalMatrix) {
628                     layer->updateExternalMatrix(fExternalMatrix,
629                                                 fExternalInverse);
630                 }
631             } while ((layer = layer->fNext) != NULL);
632         }
633         fDeviceCMDirty = false;
634     }
635 }
636 
prepareForDeviceDraw(SkDevice * device,const SkMatrix & matrix,const SkRegion & clip,const SkClipStack & clipStack)637 void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
638                                     const SkRegion& clip,
639                                     const SkClipStack& clipStack) {
640     SkASSERT(device);
641     if (fLastDeviceToGainFocus != device) {
642         device->gainFocus(this, matrix, clip, clipStack);
643         fLastDeviceToGainFocus = device;
644     }
645 }
646 
647 ///////////////////////////////////////////////////////////////////////////////
648 
internalSave(SaveFlags flags)649 int SkCanvas::internalSave(SaveFlags flags) {
650     int saveCount = this->getSaveCount(); // record this before the actual save
651 
652     MCRec* newTop = (MCRec*)fMCStack.push_back();
653     new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
654 
655     newTop->fNext = fMCRec;
656     fMCRec = newTop;
657 
658     fClipStack.save();
659     SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
660 
661     return saveCount;
662 }
663 
save(SaveFlags flags)664 int SkCanvas::save(SaveFlags flags) {
665     // call shared impl
666     return this->internalSave(flags);
667 }
668 
669 #define C32MASK (1 << SkBitmap::kARGB_8888_Config)
670 #define C16MASK (1 << SkBitmap::kRGB_565_Config)
671 #define C8MASK  (1 << SkBitmap::kA8_Config)
672 
resolve_config(SkCanvas * canvas,const SkIRect & bounds,SkCanvas::SaveFlags flags,bool * isOpaque)673 static SkBitmap::Config resolve_config(SkCanvas* canvas,
674                                        const SkIRect& bounds,
675                                        SkCanvas::SaveFlags flags,
676                                        bool* isOpaque) {
677     *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
678 
679 #if 0
680     // loop through and union all the configs we may draw into
681     uint32_t configMask = 0;
682     for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
683     {
684         SkDevice* device = canvas->getLayerDevice(i);
685         if (device->intersects(bounds))
686             configMask |= 1 << device->config();
687     }
688 
689     // if the caller wants alpha or fullcolor, we can't return 565
690     if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
691                  SkCanvas::kHasAlphaLayer_SaveFlag))
692         configMask &= ~C16MASK;
693 
694     switch (configMask) {
695     case C8MASK:    // if we only have A8, return that
696         return SkBitmap::kA8_Config;
697 
698     case C16MASK:   // if we only have 565, return that
699         return SkBitmap::kRGB_565_Config;
700 
701     default:
702         return SkBitmap::kARGB_8888_Config; // default answer
703     }
704 #else
705     return SkBitmap::kARGB_8888_Config; // default answer
706 #endif
707 }
708 
bounds_affects_clip(SkCanvas::SaveFlags flags)709 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
710     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
711 }
712 
clipRectBounds(const SkRect * bounds,SaveFlags flags,SkIRect * intersection)713 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
714                                SkIRect* intersection) {
715     SkIRect clipBounds;
716     if (!this->getClipDeviceBounds(&clipBounds)) {
717         return false;
718     }
719     SkIRect ir;
720     if (NULL != bounds) {
721         SkRect r;
722 
723         this->getTotalMatrix().mapRect(&r, *bounds);
724         r.roundOut(&ir);
725         // early exit if the layer's bounds are clipped out
726         if (!ir.intersect(clipBounds)) {
727             if (bounds_affects_clip(flags)) {
728                 fMCRec->fRasterClip->setEmpty();
729             }
730             return false;
731         }
732     } else {    // no user bounds, so just use the clip
733         ir = clipBounds;
734     }
735 
736     fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
737 
738     // early exit if the clip is now empty
739     if (bounds_affects_clip(flags) &&
740         !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) {
741         return false;
742     }
743 
744     if (intersection) {
745         *intersection = ir;
746     }
747     return true;
748 }
749 
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)750 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
751                         SaveFlags flags) {
752     // do this before we create the layer. We don't call the public save() since
753     // that would invoke a possibly overridden virtual
754     int count = this->internalSave(flags);
755 
756     fDeviceCMDirty = true;
757 
758     SkIRect ir;
759     if (!this->clipRectBounds(bounds, flags, &ir)) {
760         return count;
761     }
762 
763     // Kill the imagefilter if our device doesn't allow it
764     SkLazyPaint lazyP;
765     if (paint && paint->getImageFilter()) {
766         if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
767             SkPaint* p = lazyP.set(*paint);
768             p->setImageFilter(NULL);
769             paint = p;
770         }
771     }
772 
773     bool isOpaque;
774     SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
775 
776     SkDevice* device;
777     if (paint && paint->getImageFilter()) {
778         device = this->createCompatibleDevice(config, ir.width(), ir.height(),
779                                               isOpaque);
780     } else {
781         device = this->createLayerDevice(config, ir.width(), ir.height(),
782                                          isOpaque);
783     }
784     if (NULL == device) {
785         SkDebugf("Unable to create device for layer.");
786         return count;
787     }
788 
789     device->setOrigin(ir.fLeft, ir.fTop);
790     DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
791     device->unref();
792 
793     layer->fNext = fMCRec->fTopLayer;
794     fMCRec->fLayer = layer;
795     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
796 
797     fLayerCount += 1;
798     return count;
799 }
800 
saveLayerAlpha(const SkRect * bounds,U8CPU alpha,SaveFlags flags)801 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
802                              SaveFlags flags) {
803     if (0xFF == alpha) {
804         return this->saveLayer(bounds, NULL, flags);
805     } else {
806         SkPaint tmpPaint;
807         tmpPaint.setAlpha(alpha);
808         return this->saveLayer(bounds, &tmpPaint, flags);
809     }
810 }
811 
restore()812 void SkCanvas::restore() {
813     // check for underflow
814     if (fMCStack.count() > 1) {
815         this->internalRestore();
816     }
817 }
818 
internalRestore()819 void SkCanvas::internalRestore() {
820     SkASSERT(fMCStack.count() != 0);
821 
822     fDeviceCMDirty = true;
823     fLocalBoundsCompareTypeDirty = true;
824     fLocalBoundsCompareTypeDirtyBW = true;
825 
826     fClipStack.restore();
827     // reserve our layer (if any)
828     DeviceCM* layer = fMCRec->fLayer;   // may be null
829     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
830     fMCRec->fLayer = NULL;
831 
832     // now do the normal restore()
833     fMCRec->~MCRec();       // balanced in save()
834     fMCStack.pop_back();
835     fMCRec = (MCRec*)fMCStack.back();
836 
837     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
838         since if we're being recorded, we don't want to record this (the
839         recorder will have already recorded the restore).
840     */
841     if (NULL != layer) {
842         if (layer->fNext) {
843             const SkIPoint& origin = layer->fDevice->getOrigin();
844             this->drawDevice(layer->fDevice, origin.x(), origin.y(),
845                              layer->fPaint);
846             // reset this, since drawDevice will have set it to true
847             fDeviceCMDirty = true;
848 
849             SkASSERT(fLayerCount > 0);
850             fLayerCount -= 1;
851         }
852         SkDELETE(layer);
853     }
854 
855     SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
856 }
857 
getSaveCount() const858 int SkCanvas::getSaveCount() const {
859     return fMCStack.count();
860 }
861 
restoreToCount(int count)862 void SkCanvas::restoreToCount(int count) {
863     // sanity check
864     if (count < 1) {
865         count = 1;
866     }
867 
868     int n = this->getSaveCount() - count;
869     for (int i = 0; i < n; ++i) {
870         this->restore();
871     }
872 }
873 
isDrawingToLayer() const874 bool SkCanvas::isDrawingToLayer() const {
875     return fLayerCount > 0;
876 }
877 
878 /////////////////////////////////////////////////////////////////////////////
879 
880 // can't draw it if its empty, or its too big for a fixed-point width or height
reject_bitmap(const SkBitmap & bitmap)881 static bool reject_bitmap(const SkBitmap& bitmap) {
882     return  bitmap.width() <= 0 || bitmap.height() <= 0
883 #ifndef SK_ALLOW_OVER_32K_BITMAPS
884             || bitmap.width() > 32767 || bitmap.height() > 32767
885 #endif
886             ;
887 }
888 
internalDrawBitmap(const SkBitmap & bitmap,const SkIRect * srcRect,const SkMatrix & matrix,const SkPaint * paint)889 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
890                                 const SkMatrix& matrix, const SkPaint* paint) {
891     if (reject_bitmap(bitmap)) {
892         return;
893     }
894 
895     SkLazyPaint lazy;
896     if (NULL == paint) {
897         paint = lazy.init();
898     }
899     this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
900 }
901 
902 #include "SkImageFilter.h"
903 
904 class DeviceImageFilterProxy : public SkImageFilter::Proxy {
905 public:
DeviceImageFilterProxy(SkDevice * device)906     DeviceImageFilterProxy(SkDevice* device) : fDevice(device) {}
907 
908     virtual SkDevice* createDevice(int w, int h) SK_OVERRIDE;
909     virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
910                              const SkMatrix& ctm,
911                              SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
912 
913 private:
914     SkDevice* fDevice;
915 };
916 
createDevice(int w,int h)917 SkDevice* DeviceImageFilterProxy::createDevice(int w, int h) {
918     return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
919                                            w, h, false);
920 }
921 
filterImage(SkImageFilter * filter,const SkBitmap & src,const SkMatrix & ctm,SkBitmap * result,SkIPoint * offset)922 bool DeviceImageFilterProxy::filterImage(SkImageFilter* filter,
923                                          const SkBitmap& src,
924                                          const SkMatrix& ctm,
925                                          SkBitmap* result,
926                                          SkIPoint* offset) {
927     return fDevice->filterImage(filter, src, ctm, result, offset);
928 }
929 
drawDevice(SkDevice * srcDev,int x,int y,const SkPaint * paint)930 void SkCanvas::drawDevice(SkDevice* srcDev, int x, int y,
931                           const SkPaint* paint) {
932     SkPaint tmp;
933     if (NULL == paint) {
934         tmp.setDither(true);
935         paint = &tmp;
936     }
937 
938     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
939     while (iter.next()) {
940         SkDevice* dstDev = iter.fDevice;
941         paint = &looper.paint();
942         SkImageFilter* filter = paint->getImageFilter();
943         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
944         if (filter) {
945             DeviceImageFilterProxy proxy(dstDev);
946             SkBitmap dst;
947             const SkBitmap& src = srcDev->accessBitmap(false);
948             if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
949                 SkPaint tmp(*paint);
950                 tmp.setImageFilter(NULL);
951                 dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmp);
952             }
953         } else {
954             dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
955         }
956     }
957     LOOPER_END
958 }
959 
960 /////////////////////////////////////////////////////////////////////////////
961 
translate(SkScalar dx,SkScalar dy)962 bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
963     fDeviceCMDirty = true;
964     fLocalBoundsCompareTypeDirty = true;
965     fLocalBoundsCompareTypeDirtyBW = true;
966     return fMCRec->fMatrix->preTranslate(dx, dy);
967 }
968 
scale(SkScalar sx,SkScalar sy)969 bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
970     fDeviceCMDirty = true;
971     fLocalBoundsCompareTypeDirty = true;
972     fLocalBoundsCompareTypeDirtyBW = true;
973     return fMCRec->fMatrix->preScale(sx, sy);
974 }
975 
rotate(SkScalar degrees)976 bool SkCanvas::rotate(SkScalar degrees) {
977     fDeviceCMDirty = true;
978     fLocalBoundsCompareTypeDirty = true;
979     fLocalBoundsCompareTypeDirtyBW = true;
980     return fMCRec->fMatrix->preRotate(degrees);
981 }
982 
skew(SkScalar sx,SkScalar sy)983 bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
984     fDeviceCMDirty = true;
985     fLocalBoundsCompareTypeDirty = true;
986     fLocalBoundsCompareTypeDirtyBW = true;
987     return fMCRec->fMatrix->preSkew(sx, sy);
988 }
989 
concat(const SkMatrix & matrix)990 bool SkCanvas::concat(const SkMatrix& matrix) {
991     fDeviceCMDirty = true;
992     fLocalBoundsCompareTypeDirty = true;
993     fLocalBoundsCompareTypeDirtyBW = true;
994     return fMCRec->fMatrix->preConcat(matrix);
995 }
996 
setMatrix(const SkMatrix & matrix)997 void SkCanvas::setMatrix(const SkMatrix& matrix) {
998     fDeviceCMDirty = true;
999     fLocalBoundsCompareTypeDirty = true;
1000     fLocalBoundsCompareTypeDirtyBW = true;
1001     *fMCRec->fMatrix = matrix;
1002 }
1003 
1004 // this is not virtual, so it must call a virtual method so that subclasses
1005 // will see its action
resetMatrix()1006 void SkCanvas::resetMatrix() {
1007     SkMatrix matrix;
1008 
1009     matrix.reset();
1010     this->setMatrix(matrix);
1011 }
1012 
1013 //////////////////////////////////////////////////////////////////////////////
1014 
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)1015 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1016     AutoValidateClip avc(this);
1017 
1018     fDeviceCMDirty = true;
1019     fLocalBoundsCompareTypeDirty = true;
1020     fLocalBoundsCompareTypeDirtyBW = true;
1021 
1022     if (fMCRec->fMatrix->rectStaysRect()) {
1023         // for these simpler matrices, we can stay a rect ever after applying
1024         // the matrix. This means we don't have to a) make a path, and b) tell
1025         // the region code to scan-convert the path, only to discover that it
1026         // is really just a rect.
1027         SkRect      r;
1028 
1029         fMCRec->fMatrix->mapRect(&r, rect);
1030         fClipStack.clipDevRect(r, op, doAA);
1031         return fMCRec->fRasterClip->op(r, op, doAA);
1032     } else {
1033         // since we're rotate or some such thing, we convert the rect to a path
1034         // and clip against that, since it can handle any matrix. However, to
1035         // avoid recursion in the case where we are subclassed (e.g. Pictures)
1036         // we explicitly call "our" version of clipPath.
1037         SkPath  path;
1038 
1039         path.addRect(rect);
1040         return this->SkCanvas::clipPath(path, op, doAA);
1041     }
1042 }
1043 
clipPathHelper(const SkCanvas * canvas,SkRasterClip * currClip,const SkPath & devPath,SkRegion::Op op,bool doAA)1044 static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
1045                            const SkPath& devPath, SkRegion::Op op, bool doAA) {
1046     // base is used to limit the size (and therefore memory allocation) of the
1047     // region that results from scan converting devPath.
1048     SkRegion base;
1049 
1050     if (SkRegion::kIntersect_Op == op) {
1051         // since we are intersect, we can do better (tighter) with currRgn's
1052         // bounds, than just using the device. However, if currRgn is complex,
1053         // our region blitter may hork, so we do that case in two steps.
1054         if (currClip->isRect()) {
1055             return currClip->setPath(devPath, *currClip, doAA);
1056         } else {
1057             base.setRect(currClip->getBounds());
1058             SkRasterClip clip;
1059             clip.setPath(devPath, base, doAA);
1060             return currClip->op(clip, op);
1061         }
1062     } else {
1063         const SkDevice* device = canvas->getDevice();
1064         if (!device) {
1065             return currClip->setEmpty();
1066         }
1067 
1068         base.setRect(0, 0, device->width(), device->height());
1069 
1070         if (SkRegion::kReplace_Op == op) {
1071             return currClip->setPath(devPath, base, doAA);
1072         } else {
1073             SkRasterClip clip;
1074             clip.setPath(devPath, base, doAA);
1075             return currClip->op(clip, op);
1076         }
1077     }
1078 }
1079 
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)1080 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1081     AutoValidateClip avc(this);
1082 
1083     fDeviceCMDirty = true;
1084     fLocalBoundsCompareTypeDirty = true;
1085     fLocalBoundsCompareTypeDirtyBW = true;
1086 
1087     SkPath devPath;
1088     path.transform(*fMCRec->fMatrix, &devPath);
1089 
1090     // Check if the transfomation, or the original path itself
1091     // made us empty. Note this can also happen if we contained NaN
1092     // values. computing the bounds detects this, and will set our
1093     // bounds to empty if that is the case. (see SkRect::set(pts, count))
1094     if (devPath.getBounds().isEmpty()) {
1095         // resetting the path will remove any NaN or other wanky values
1096         // that might upset our scan converter.
1097         devPath.reset();
1098     }
1099 
1100     // if we called path.swap() we could avoid a deep copy of this path
1101     fClipStack.clipDevPath(devPath, op, doAA);
1102 
1103     return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
1104 }
1105 
clipRegion(const SkRegion & rgn,SkRegion::Op op)1106 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1107     AutoValidateClip avc(this);
1108 
1109     fDeviceCMDirty = true;
1110     fLocalBoundsCompareTypeDirty = true;
1111     fLocalBoundsCompareTypeDirtyBW = true;
1112 
1113     // todo: signal fClipStack that we have a region, and therefore (I guess)
1114     // we have to ignore it, and use the region directly?
1115     fClipStack.clipDevRect(rgn.getBounds());
1116 
1117     return fMCRec->fRasterClip->op(rgn, op);
1118 }
1119 
1120 #ifdef SK_DEBUG
validateClip() const1121 void SkCanvas::validateClip() const {
1122     // construct clipRgn from the clipstack
1123     const SkDevice* device = this->getDevice();
1124     if (!device) {
1125         SkASSERT(this->getTotalClip().isEmpty());
1126         return;
1127     }
1128 
1129     SkIRect ir;
1130     ir.set(0, 0, device->width(), device->height());
1131     SkRasterClip tmpClip(ir);
1132 
1133     SkClipStack::B2FIter                iter(fClipStack);
1134     const SkClipStack::B2FIter::Clip*   clip;
1135     while ((clip = iter.next()) != NULL) {
1136         if (clip->fPath) {
1137             clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA);
1138         } else if (clip->fRect) {
1139             clip->fRect->round(&ir);
1140             tmpClip.op(ir, clip->fOp);
1141         } else {
1142             tmpClip.setEmpty();
1143         }
1144     }
1145 
1146 #if 0   // enable this locally for testing
1147     // now compare against the current rgn
1148     const SkRegion& rgn = this->getTotalClip();
1149     SkASSERT(rgn == tmpClip);
1150 #endif
1151 }
1152 #endif
1153 
1154 ///////////////////////////////////////////////////////////////////////////////
1155 
computeLocalClipBoundsCompareType(EdgeType et) const1156 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
1157     SkRect r;
1158     SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType :
1159             fLocalBoundsCompareTypeBW;
1160 
1161     if (!this->getClipBounds(&r, et)) {
1162         rCompare.setEmpty();
1163     } else {
1164         rCompare.set(SkScalarToCompareType(r.fLeft),
1165                      SkScalarToCompareType(r.fTop),
1166                      SkScalarToCompareType(r.fRight),
1167                      SkScalarToCompareType(r.fBottom));
1168     }
1169 }
1170 
1171 /*  current impl ignores edgetype, and relies on
1172     getLocalClipBoundsCompareType(), which always returns a value assuming
1173     antialiasing (worst case)
1174  */
quickReject(const SkRect & rect,EdgeType et) const1175 bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
1176 
1177     if (!rect.isFinite())
1178         return true;
1179 
1180     if (fMCRec->fRasterClip->isEmpty()) {
1181         return true;
1182     }
1183 
1184     if (fMCRec->fMatrix->hasPerspective()) {
1185         SkRect dst;
1186         fMCRec->fMatrix->mapRect(&dst, rect);
1187         SkIRect idst;
1188         dst.roundOut(&idst);
1189         return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1190     } else {
1191         const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et);
1192 
1193         // for speed, do the most likely reject compares first
1194         SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
1195         SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
1196         if (userT >= clipR.fBottom || userB <= clipR.fTop) {
1197             return true;
1198         }
1199         SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
1200         SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
1201         if (userL >= clipR.fRight || userR <= clipR.fLeft) {
1202             return true;
1203         }
1204         return false;
1205     }
1206 }
1207 
quickReject(const SkPath & path,EdgeType et) const1208 bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
1209     return path.isEmpty() || this->quickReject(path.getBounds(), et);
1210 }
1211 
pinIntForScalar(int x)1212 static inline int pinIntForScalar(int x) {
1213 #ifdef SK_SCALAR_IS_FIXED
1214     if (x < SK_MinS16) {
1215         x = SK_MinS16;
1216     } else if (x > SK_MaxS16) {
1217         x = SK_MaxS16;
1218     }
1219 #endif
1220     return x;
1221 }
1222 
getClipBounds(SkRect * bounds,EdgeType et) const1223 bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
1224     SkIRect ibounds;
1225     if (!getClipDeviceBounds(&ibounds)) {
1226         return false;
1227     }
1228 
1229     SkMatrix inverse;
1230     // if we can't invert the CTM, we can't return local clip bounds
1231     if (!fMCRec->fMatrix->invert(&inverse)) {
1232         if (bounds) {
1233             bounds->setEmpty();
1234         }
1235         return false;
1236     }
1237 
1238     if (NULL != bounds) {
1239         SkRect r;
1240         // adjust it outwards if we are antialiasing
1241         int inset = (kAA_EdgeType == et);
1242 
1243         // SkRect::iset() will correctly assert if we pass a value out of range
1244         // (when SkScalar==fixed), so we pin to legal values. This does not
1245         // really returnt the correct answer, but its the best we can do given
1246         // that we've promised to return SkRect (even though we support devices
1247         // that can be larger than 32K in width or height).
1248         r.iset(pinIntForScalar(ibounds.fLeft - inset),
1249                pinIntForScalar(ibounds.fTop - inset),
1250                pinIntForScalar(ibounds.fRight + inset),
1251                pinIntForScalar(ibounds.fBottom + inset));
1252         inverse.mapRect(bounds, r);
1253     }
1254     return true;
1255 }
1256 
getClipDeviceBounds(SkIRect * bounds) const1257 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1258     const SkRasterClip& clip = *fMCRec->fRasterClip;
1259     if (clip.isEmpty()) {
1260         if (bounds) {
1261             bounds->setEmpty();
1262         }
1263         return false;
1264     }
1265 
1266     if (NULL != bounds) {
1267         *bounds = clip.getBounds();
1268     }
1269     return true;
1270 }
1271 
getTotalMatrix() const1272 const SkMatrix& SkCanvas::getTotalMatrix() const {
1273     return *fMCRec->fMatrix;
1274 }
1275 
getClipType() const1276 SkCanvas::ClipType SkCanvas::getClipType() const {
1277     if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
1278     if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
1279     return kComplex_ClipType;
1280 }
1281 
getTotalClip() const1282 const SkRegion& SkCanvas::getTotalClip() const {
1283     return fMCRec->fRasterClip->forceGetBW();
1284 }
1285 
getTotalClipStack() const1286 const SkClipStack& SkCanvas::getTotalClipStack() const {
1287     return fClipStack;
1288 }
1289 
setExternalMatrix(const SkMatrix * matrix)1290 void SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
1291     if (NULL == matrix || matrix->isIdentity()) {
1292         if (fUseExternalMatrix) {
1293             fDeviceCMDirty = true;
1294         }
1295         fUseExternalMatrix = false;
1296     } else {
1297         fUseExternalMatrix = true;
1298         fDeviceCMDirty = true;  // |= (fExternalMatrix != *matrix)
1299 
1300         fExternalMatrix = *matrix;
1301         matrix->invert(&fExternalInverse);
1302     }
1303 }
1304 
createLayerDevice(SkBitmap::Config config,int width,int height,bool isOpaque)1305 SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
1306                                       int width, int height,
1307                                       bool isOpaque) {
1308     SkDevice* device = this->getTopDevice();
1309     if (device) {
1310         return device->createCompatibleDeviceForSaveLayer(config, width, height,
1311                                                           isOpaque);
1312     } else {
1313         return NULL;
1314     }
1315 }
1316 
createCompatibleDevice(SkBitmap::Config config,int width,int height,bool isOpaque)1317 SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
1318                                            int width, int height,
1319                                            bool isOpaque) {
1320     SkDevice* device = this->getDevice();
1321     if (device) {
1322         return device->createCompatibleDevice(config, width, height, isOpaque);
1323     } else {
1324         return NULL;
1325     }
1326 }
1327 
1328 
1329 //////////////////////////////////////////////////////////////////////////////
1330 //  These are the virtual drawing methods
1331 //////////////////////////////////////////////////////////////////////////////
1332 
clear(SkColor color)1333 void SkCanvas::clear(SkColor color) {
1334     SkDrawIter  iter(this);
1335 
1336     while (iter.next()) {
1337         iter.fDevice->clear(color);
1338     }
1339 }
1340 
drawPaint(const SkPaint & paint)1341 void SkCanvas::drawPaint(const SkPaint& paint) {
1342     this->internalDrawPaint(paint);
1343 }
1344 
internalDrawPaint(const SkPaint & paint)1345 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1346     LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
1347 
1348     while (iter.next()) {
1349         iter.fDevice->drawPaint(iter, looper.paint());
1350     }
1351 
1352     LOOPER_END
1353 }
1354 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1355 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1356                           const SkPaint& paint) {
1357     if ((long)count <= 0) {
1358         return;
1359     }
1360 
1361     SkASSERT(pts != NULL);
1362 
1363     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1364 
1365     while (iter.next()) {
1366         iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1367     }
1368 
1369     LOOPER_END
1370 }
1371 
drawRect(const SkRect & r,const SkPaint & paint)1372 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1373     if (paint.canComputeFastBounds()) {
1374         SkRect storage;
1375         if (this->quickReject(paint.computeFastBounds(r, &storage),
1376                               paint2EdgeType(&paint))) {
1377             return;
1378         }
1379     }
1380 
1381     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
1382 
1383     while (iter.next()) {
1384         iter.fDevice->drawRect(iter, r, looper.paint());
1385     }
1386 
1387     LOOPER_END
1388 }
1389 
drawPath(const SkPath & path,const SkPaint & paint)1390 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1391     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1392         SkRect storage;
1393         const SkRect& bounds = path.getBounds();
1394         if (this->quickReject(paint.computeFastBounds(bounds, &storage),
1395                               paint2EdgeType(&paint))) {
1396             return;
1397         }
1398     }
1399     if (path.isEmpty()) {
1400         if (path.isInverseFillType()) {
1401             this->internalDrawPaint(paint);
1402         }
1403         return;
1404     }
1405 
1406     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1407 
1408     while (iter.next()) {
1409         iter.fDevice->drawPath(iter, path, looper.paint());
1410     }
1411 
1412     LOOPER_END
1413 }
1414 
drawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)1415 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1416                           const SkPaint* paint) {
1417     SkDEBUGCODE(bitmap.validate();)
1418 
1419     if (NULL == paint || paint->canComputeFastBounds()) {
1420         SkRect bounds = {
1421             x, y,
1422             x + SkIntToScalar(bitmap.width()),
1423             y + SkIntToScalar(bitmap.height())
1424         };
1425         if (paint) {
1426             (void)paint->computeFastBounds(bounds, &bounds);
1427         }
1428         if (this->quickReject(bounds, paint2EdgeType(paint))) {
1429             return;
1430         }
1431     }
1432 
1433     SkMatrix matrix;
1434     matrix.setTranslate(x, y);
1435     this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1436 }
1437 
1438 // 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)1439 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
1440                                       const SkRect& dst, const SkPaint* paint) {
1441     if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1442         return;
1443     }
1444 
1445     // do this now, to avoid the cost of calling extract for RLE bitmaps
1446     if (NULL == paint || paint->canComputeFastBounds()) {
1447         SkRect storage;
1448         const SkRect* bounds = &dst;
1449         if (paint) {
1450             bounds = &paint->computeFastBounds(dst, &storage);
1451         }
1452         if (this->quickReject(*bounds, paint2EdgeType(paint))) {
1453             return;
1454         }
1455     }
1456 
1457     const SkBitmap* bitmapPtr = &bitmap;
1458 
1459     SkMatrix matrix;
1460     SkRect tmpSrc;
1461     if (src) {
1462         tmpSrc.set(*src);
1463         // if the extract process clipped off the top or left of the
1464         // original, we adjust for that here to get the position right.
1465         if (tmpSrc.fLeft > 0) {
1466             tmpSrc.fRight -= tmpSrc.fLeft;
1467             tmpSrc.fLeft = 0;
1468         }
1469         if (tmpSrc.fTop > 0) {
1470             tmpSrc.fBottom -= tmpSrc.fTop;
1471             tmpSrc.fTop = 0;
1472         }
1473     } else {
1474         tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()),
1475                    SkIntToScalar(bitmap.height()));
1476     }
1477     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1478 
1479     // ensure that src is "valid" before we pass it to our internal routines
1480     // and to SkDevice. i.e. sure it is contained inside the original bitmap.
1481     SkIRect tmpISrc;
1482     if (src) {
1483         tmpISrc.set(0, 0, bitmap.width(), bitmap.height());
1484         if (!tmpISrc.intersect(*src)) {
1485             return;
1486         }
1487         src = &tmpISrc;
1488     }
1489     this->internalDrawBitmap(*bitmapPtr, src, matrix, paint);
1490 }
1491 
drawBitmapRect(const SkBitmap & bitmap,const SkIRect * src,const SkRect & dst,const SkPaint * paint)1492 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
1493                               const SkRect& dst, const SkPaint* paint) {
1494     SkDEBUGCODE(bitmap.validate();)
1495     this->internalDrawBitmapRect(bitmap, src, dst, paint);
1496 }
1497 
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)1498 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1499                                 const SkPaint* paint) {
1500     SkDEBUGCODE(bitmap.validate();)
1501     this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1502 }
1503 
commonDrawBitmap(const SkBitmap & bitmap,const SkIRect * srcRect,const SkMatrix & matrix,const SkPaint & paint)1504 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
1505                                 const SkMatrix& matrix, const SkPaint& paint) {
1506     SkDEBUGCODE(bitmap.validate();)
1507 
1508     LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1509 
1510     while (iter.next()) {
1511         iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
1512     }
1513 
1514     LOOPER_END
1515 }
1516 
internalDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1517 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1518                                       const SkIRect& center, const SkRect& dst,
1519                                       const SkPaint* paint) {
1520     if (NULL == paint || paint->canComputeFastBounds()) {
1521         SkRect storage;
1522         const SkRect* bounds = &dst;
1523         if (paint) {
1524             bounds = &paint->computeFastBounds(dst, &storage);
1525         }
1526         if (this->quickReject(*bounds, paint2EdgeType(paint))) {
1527             return;
1528         }
1529     }
1530 
1531     const int32_t w = bitmap.width();
1532     const int32_t h = bitmap.height();
1533 
1534     SkIRect c = center;
1535     // pin center to the bounds of the bitmap
1536     c.fLeft = SkMax32(0, center.fLeft);
1537     c.fTop = SkMax32(0, center.fTop);
1538     c.fRight = SkPin32(center.fRight, c.fLeft, w);
1539     c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1540 
1541     const int32_t srcX[4] = { 0, c.fLeft, c.fRight, w };
1542     const int32_t srcY[4] = { 0, c.fTop, c.fBottom, h };
1543     SkScalar dstX[4] = {
1544         dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1545         dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1546     };
1547     SkScalar dstY[4] = {
1548         dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1549         dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1550     };
1551 
1552     if (dstX[1] > dstX[2]) {
1553         dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1554         dstX[2] = dstX[1];
1555     }
1556 
1557     if (dstY[1] > dstY[2]) {
1558         dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1559         dstY[2] = dstY[1];
1560     }
1561 
1562     SkIRect s;
1563     SkRect  d;
1564     for (int y = 0; y < 3; y++) {
1565         s.fTop = srcY[y];
1566         s.fBottom = srcY[y+1];
1567         d.fTop = dstY[y];
1568         d.fBottom = dstY[y+1];
1569         for (int x = 0; x < 3; x++) {
1570             s.fLeft = srcX[x];
1571             s.fRight = srcX[x+1];
1572             d.fLeft = dstX[x];
1573             d.fRight = dstX[x+1];
1574             this->internalDrawBitmapRect(bitmap, &s, d, paint);
1575         }
1576     }
1577 }
1578 
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1579 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1580                               const SkRect& dst, const SkPaint* paint) {
1581     SkDEBUGCODE(bitmap.validate();)
1582 
1583     // Need a device entry-point, so gpu can use a mesh
1584     this->internalDrawBitmapNine(bitmap, center, dst, paint);
1585 }
1586 
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint * paint)1587 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1588                           const SkPaint* paint) {
1589     SkDEBUGCODE(bitmap.validate();)
1590 
1591     if (reject_bitmap(bitmap)) {
1592         return;
1593     }
1594 
1595     SkPaint tmp;
1596     if (NULL == paint) {
1597         paint = &tmp;
1598     }
1599 
1600     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1601 
1602     while (iter.next()) {
1603         iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
1604                                  looper.paint());
1605     }
1606     LOOPER_END
1607 }
1608 
1609 class SkDeviceFilteredPaint {
1610 public:
SkDeviceFilteredPaint(SkDevice * device,const SkPaint & paint)1611     SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
1612         SkDevice::TextFlags flags;
1613         if (device->filterTextFlags(paint, &flags)) {
1614             SkPaint* newPaint = fLazy.set(paint);
1615             newPaint->setFlags(flags.fFlags);
1616             newPaint->setHinting(flags.fHinting);
1617             fPaint = newPaint;
1618         } else {
1619             fPaint = &paint;
1620         }
1621     }
1622 
paint() const1623     const SkPaint& paint() const { return *fPaint; }
1624 
1625 private:
1626     const SkPaint*  fPaint;
1627     SkLazyPaint     fLazy;
1628 };
1629 
DrawRect(const SkDraw & draw,const SkPaint & paint,const SkRect & r,SkScalar textSize)1630 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
1631                         const SkRect& r, SkScalar textSize) {
1632     if (paint.getStyle() == SkPaint::kFill_Style) {
1633         draw.fDevice->drawRect(draw, r, paint);
1634     } else {
1635         SkPaint p(paint);
1636         p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1637         draw.fDevice->drawRect(draw, r, p);
1638     }
1639 }
1640 
DrawTextDecorations(const SkDraw & draw,const SkPaint & paint,const char text[],size_t byteLength,SkScalar x,SkScalar y)1641 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1642                                    const char text[], size_t byteLength,
1643                                    SkScalar x, SkScalar y) {
1644     SkASSERT(byteLength == 0 || text != NULL);
1645 
1646     // nothing to draw
1647     if (text == NULL || byteLength == 0 ||
1648         draw.fClip->isEmpty() ||
1649         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1650         return;
1651     }
1652 
1653     SkScalar    width = 0;
1654     SkPoint     start;
1655 
1656     start.set(0, 0);    // to avoid warning
1657     if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1658                             SkPaint::kStrikeThruText_Flag)) {
1659         width = paint.measureText(text, byteLength);
1660 
1661         SkScalar offsetX = 0;
1662         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1663             offsetX = SkScalarHalf(width);
1664         } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1665             offsetX = width;
1666         }
1667         start.set(x - offsetX, y);
1668     }
1669 
1670     if (0 == width) {
1671         return;
1672     }
1673 
1674     uint32_t flags = paint.getFlags();
1675 
1676     if (flags & (SkPaint::kUnderlineText_Flag |
1677                  SkPaint::kStrikeThruText_Flag)) {
1678         SkScalar textSize = paint.getTextSize();
1679         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1680         SkRect   r;
1681 
1682         r.fLeft = start.fX;
1683         r.fRight = start.fX + width;
1684 
1685         if (flags & SkPaint::kUnderlineText_Flag) {
1686             SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1687                                              start.fY);
1688             r.fTop = offset;
1689             r.fBottom = offset + height;
1690             DrawRect(draw, paint, r, textSize);
1691         }
1692         if (flags & SkPaint::kStrikeThruText_Flag) {
1693             SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1694                                              start.fY);
1695             r.fTop = offset;
1696             r.fBottom = offset + height;
1697             DrawRect(draw, paint, r, textSize);
1698         }
1699     }
1700 }
1701 
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)1702 void SkCanvas::drawText(const void* text, size_t byteLength,
1703                         SkScalar x, SkScalar y, const SkPaint& paint) {
1704     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1705 
1706     while (iter.next()) {
1707         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1708         iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
1709         DrawTextDecorations(iter, dfp.paint(),
1710                             static_cast<const char*>(text), byteLength, x, y);
1711     }
1712 
1713     LOOPER_END
1714 }
1715 
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)1716 void SkCanvas::drawPosText(const void* text, size_t byteLength,
1717                            const SkPoint pos[], const SkPaint& paint) {
1718     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1719 
1720     while (iter.next()) {
1721         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1722         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1723                                   dfp.paint());
1724     }
1725 
1726     LOOPER_END
1727 }
1728 
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)1729 void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1730                             const SkScalar xpos[], SkScalar constY,
1731                             const SkPaint& paint) {
1732     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1733 
1734     while (iter.next()) {
1735         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1736         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1737                                   dfp.paint());
1738     }
1739 
1740     LOOPER_END
1741 }
1742 
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)1743 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1744                               const SkPath& path, const SkMatrix* matrix,
1745                               const SkPaint& paint) {
1746     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1747 
1748     while (iter.next()) {
1749         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1750                                      matrix, looper.paint());
1751     }
1752 
1753     LOOPER_END
1754 }
1755 
1756 #ifdef SK_BUILD_FOR_ANDROID
drawPosTextOnPath(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint,const SkPath & path,const SkMatrix * matrix)1757 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
1758                                  const SkPoint pos[], const SkPaint& paint,
1759                                  const SkPath& path, const SkMatrix* matrix) {
1760     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1761 
1762     while (iter.next()) {
1763         iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
1764                                         looper.paint(), path, matrix);
1765     }
1766 
1767     LOOPER_END
1768 }
1769 #endif
1770 
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)1771 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1772                             const SkPoint verts[], const SkPoint texs[],
1773                             const SkColor colors[], SkXfermode* xmode,
1774                             const uint16_t indices[], int indexCount,
1775                             const SkPaint& paint) {
1776     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1777 
1778     while (iter.next()) {
1779         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1780                                    colors, xmode, indices, indexCount,
1781                                    looper.paint());
1782     }
1783 
1784     LOOPER_END
1785 }
1786 
drawData(const void * data,size_t length)1787 void SkCanvas::drawData(const void* data, size_t length) {
1788     // do nothing. Subclasses may do something with the data
1789 }
1790 
1791 //////////////////////////////////////////////////////////////////////////////
1792 // These methods are NOT virtual, and therefore must call back into virtual
1793 // methods, rather than actually drawing themselves.
1794 //////////////////////////////////////////////////////////////////////////////
1795 
drawARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b,SkXfermode::Mode mode)1796 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1797                         SkXfermode::Mode mode) {
1798     SkPaint paint;
1799 
1800     paint.setARGB(a, r, g, b);
1801     if (SkXfermode::kSrcOver_Mode != mode) {
1802         paint.setXfermodeMode(mode);
1803     }
1804     this->drawPaint(paint);
1805 }
1806 
drawColor(SkColor c,SkXfermode::Mode mode)1807 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
1808     SkPaint paint;
1809 
1810     paint.setColor(c);
1811     if (SkXfermode::kSrcOver_Mode != mode) {
1812         paint.setXfermodeMode(mode);
1813     }
1814     this->drawPaint(paint);
1815 }
1816 
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)1817 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
1818     SkPoint pt;
1819 
1820     pt.set(x, y);
1821     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1822 }
1823 
drawPoint(SkScalar x,SkScalar y,SkColor color)1824 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
1825     SkPoint pt;
1826     SkPaint paint;
1827 
1828     pt.set(x, y);
1829     paint.setColor(color);
1830     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1831 }
1832 
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)1833 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
1834                         const SkPaint& paint) {
1835     SkPoint pts[2];
1836 
1837     pts[0].set(x0, y0);
1838     pts[1].set(x1, y1);
1839     this->drawPoints(kLines_PointMode, 2, pts, paint);
1840 }
1841 
drawRectCoords(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom,const SkPaint & paint)1842 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
1843                               SkScalar right, SkScalar bottom,
1844                               const SkPaint& paint) {
1845     SkRect  r;
1846 
1847     r.set(left, top, right, bottom);
1848     this->drawRect(r, paint);
1849 }
1850 
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)1851 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
1852                           const SkPaint& paint) {
1853     if (radius < 0) {
1854         radius = 0;
1855     }
1856 
1857     SkRect  r;
1858     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
1859 
1860     if (paint.canComputeFastBounds()) {
1861         SkRect storage;
1862         if (this->quickReject(paint.computeFastBounds(r, &storage),
1863                               paint2EdgeType(&paint))) {
1864             return;
1865         }
1866     }
1867 
1868     SkPath  path;
1869     path.addOval(r);
1870     this->drawPath(path, paint);
1871 }
1872 
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)1873 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
1874                              const SkPaint& paint) {
1875     if (rx > 0 && ry > 0) {
1876         if (paint.canComputeFastBounds()) {
1877             SkRect storage;
1878             if (this->quickReject(paint.computeFastBounds(r, &storage),
1879                                   paint2EdgeType(&paint))) {
1880                 return;
1881             }
1882         }
1883 
1884         SkPath  path;
1885         path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
1886         this->drawPath(path, paint);
1887     } else {
1888         this->drawRect(r, paint);
1889     }
1890 }
1891 
drawOval(const SkRect & oval,const SkPaint & paint)1892 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1893     if (paint.canComputeFastBounds()) {
1894         SkRect storage;
1895         if (this->quickReject(paint.computeFastBounds(oval, &storage),
1896                               paint2EdgeType(&paint))) {
1897             return;
1898         }
1899     }
1900 
1901     SkPath  path;
1902     path.addOval(oval);
1903     this->drawPath(path, paint);
1904 }
1905 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1906 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
1907                        SkScalar sweepAngle, bool useCenter,
1908                        const SkPaint& paint) {
1909     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
1910         this->drawOval(oval, paint);
1911     } else {
1912         SkPath  path;
1913         if (useCenter) {
1914             path.moveTo(oval.centerX(), oval.centerY());
1915         }
1916         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
1917         if (useCenter) {
1918             path.close();
1919         }
1920         this->drawPath(path, paint);
1921     }
1922 }
1923 
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)1924 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
1925                                 const SkPath& path, SkScalar hOffset,
1926                                 SkScalar vOffset, const SkPaint& paint) {
1927     SkMatrix    matrix;
1928 
1929     matrix.setTranslate(hOffset, vOffset);
1930     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
1931 }
1932 
1933 ///////////////////////////////////////////////////////////////////////////////
1934 
drawPicture(SkPicture & picture)1935 void SkCanvas::drawPicture(SkPicture& picture) {
1936     int saveCount = save();
1937     picture.draw(this);
1938     restoreToCount(saveCount);
1939 }
1940 
1941 ///////////////////////////////////////////////////////////////////////////////
1942 ///////////////////////////////////////////////////////////////////////////////
1943 
LayerIter(SkCanvas * canvas,bool skipEmptyClips)1944 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
1945     SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
1946 
1947     SkASSERT(canvas);
1948 
1949     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
1950     fDone = !fImpl->next();
1951 }
1952 
~LayerIter()1953 SkCanvas::LayerIter::~LayerIter() {
1954     fImpl->~SkDrawIter();
1955 }
1956 
next()1957 void SkCanvas::LayerIter::next() {
1958     fDone = !fImpl->next();
1959 }
1960 
device() const1961 SkDevice* SkCanvas::LayerIter::device() const {
1962     return fImpl->getDevice();
1963 }
1964 
matrix() const1965 const SkMatrix& SkCanvas::LayerIter::matrix() const {
1966     return fImpl->getMatrix();
1967 }
1968 
paint() const1969 const SkPaint& SkCanvas::LayerIter::paint() const {
1970     const SkPaint* paint = fImpl->getPaint();
1971     if (NULL == paint) {
1972         paint = &fDefaultPaint;
1973     }
1974     return *paint;
1975 }
1976 
clip() const1977 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
x() const1978 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const1979 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
1980