• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "SkCanvas.h"
18 #include "SkBounder.h"
19 #include "SkDevice.h"
20 #include "SkDraw.h"
21 #include "SkDrawFilter.h"
22 #include "SkDrawLooper.h"
23 #include "SkPicture.h"
24 #include "SkScalarCompare.h"
25 #include "SkShape.h"
26 #include "SkTemplates.h"
27 #include "SkUtils.h"
28 #include <new>
29 
30 //#define SK_TRACE_SAVERESTORE
31 
32 #ifdef SK_TRACE_SAVERESTORE
33     static int gLayerCounter;
inc_layer()34     static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
dec_layer()35     static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
36 
37     static int gRecCounter;
inc_rec()38     static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
dec_rec()39     static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
40 
41     static int gCanvasCounter;
inc_canvas()42     static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
dec_canvas()43     static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
44 #else
45     #define inc_layer()
46     #define dec_layer()
47     #define inc_rec()
48     #define dec_rec()
49     #define inc_canvas()
50     #define dec_canvas()
51 #endif
52 
53 ///////////////////////////////////////////////////////////////////////////////
54 // Helpers for computing fast bounds for quickReject tests
55 
paint2EdgeType(const SkPaint * paint)56 static SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) {
57     return paint != NULL && paint->isAntiAlias() ?
58             SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType;
59 }
60 
61 ///////////////////////////////////////////////////////////////////////////////
62 
63 /*  This is the record we keep for each SkDevice that the user installs.
64     The clip/matrix/proc are fields that reflect the top of the save/restore
65     stack. Whenever the canvas changes, it marks a dirty flag, and then before
66     these are used (assuming we're not on a layer) we rebuild these cache
67     values: they reflect the top of the save stack, but translated and clipped
68     by the device's XY offset and bitmap-bounds.
69 */
70 struct DeviceCM {
71     DeviceCM*           fNext;
72     SkDevice*           fDevice;
73     SkRegion            fClip;
74     const SkMatrix*     fMatrix;
75 	SkPaint*			fPaint;	// may be null (in the future)
76     int16_t             fX, fY; // relative to base matrix/clip
77 
DeviceCMDeviceCM78 	DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
79             : fNext(NULL) {
80         if (NULL != device) {
81             device->ref();
82             device->lockPixels();
83         }
84         fDevice = device;
85         fX = SkToS16(x);
86         fY = SkToS16(y);
87         fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
88 	}
89 
~DeviceCMDeviceCM90 	~DeviceCM() {
91         if (NULL != fDevice) {
92             fDevice->unlockPixels();
93             fDevice->unref();
94         }
95 		SkDELETE(fPaint);
96 	}
97 
updateMCDeviceCM98     void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip,
99                   SkRegion* updateClip) {
100         int x = fX;
101         int y = fY;
102         int width = fDevice->width();
103         int height = fDevice->height();
104 
105         if ((x | y) == 0) {
106             fMatrix = &totalMatrix;
107             fClip = totalClip;
108         } else {
109             fMatrixStorage = totalMatrix;
110             fMatrixStorage.postTranslate(SkIntToScalar(-x),
111                                          SkIntToScalar(-y));
112             fMatrix = &fMatrixStorage;
113 
114             totalClip.translate(-x, -y, &fClip);
115         }
116 
117         fClip.op(0, 0, width, height, SkRegion::kIntersect_Op);
118 
119         // intersect clip, but don't translate it (yet)
120 
121         if (updateClip) {
122             updateClip->op(x, y, x + width, y + height,
123                            SkRegion::kDifference_Op);
124         }
125 
126         fDevice->setMatrixClip(*fMatrix, fClip);
127 
128 #ifdef SK_DEBUG
129         if (!fClip.isEmpty()) {
130             SkIRect deviceR;
131             deviceR.set(0, 0, width, height);
132             SkASSERT(deviceR.contains(fClip.getBounds()));
133         }
134 #endif
135     }
136 
translateClipDeviceCM137     void translateClip() {
138         if (fX | fY) {
139             fClip.translate(fX, fY);
140         }
141     }
142 
143 private:
144     SkMatrix    fMatrixStorage;
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     SkRegion*       fRegion;    // 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                 fRegionStorage = *prev->fRegion;
181                 fRegion = &fRegionStorage;
182             } else {
183                 fRegion = prev->fRegion;
184             }
185 
186             fFilter = prev->fFilter;
187             fFilter->safeRef();
188 
189             fTopLayer = prev->fTopLayer;
190         } else {   // no prev
191             fMatrixStorage.reset();
192 
193             fMatrix     = &fMatrixStorage;
194             fRegion     = &fRegionStorage;
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         fFilter->safeUnref();
205         SkDELETE(fLayer);
206         dec_rec();
207     }
208 
209 private:
210     SkMatrix    fMatrixStorage;
211     SkRegion    fRegionStorage;
212 };
213 
214 class SkDrawIter : public SkDraw {
215 public:
SkDrawIter(SkCanvas * canvas,bool skipEmptyClips=true)216     SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
217         fCanvas = canvas;
218         canvas->updateDeviceCMCache();
219 
220         fBounder = canvas->getBounder();
221         fCurrLayer = canvas->fMCRec->fTopLayer;
222         fSkipEmptyClips = skipEmptyClips;
223     }
224 
next()225     bool next() {
226         // skip over recs with empty clips
227         if (fSkipEmptyClips) {
228             while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
229                 fCurrLayer = fCurrLayer->fNext;
230             }
231         }
232 
233         if (NULL != fCurrLayer) {
234             const DeviceCM* rec = fCurrLayer;
235 
236             fMatrix = rec->fMatrix;
237             fClip   = &rec->fClip;
238             fDevice = rec->fDevice;
239             fBitmap = &fDevice->accessBitmap(true);
240             fLayerX = rec->fX;
241             fLayerY = rec->fY;
242             fPaint  = rec->fPaint;
243             SkDEBUGCODE(this->validate();)
244 
245             fCurrLayer = rec->fNext;
246             if (fBounder) {
247                 fBounder->setClip(fClip);
248             }
249 
250             // fCurrLayer may be NULL now
251 
252             fCanvas->prepareForDeviceDraw(fDevice);
253             return true;
254         }
255         return false;
256     }
257 
getX() const258     int getX() const { return fLayerX; }
getY() const259     int getY() const { return fLayerY; }
getDevice() const260     SkDevice* getDevice() const { return fDevice; }
getMatrix() const261     const SkMatrix& getMatrix() const { return *fMatrix; }
getClip() const262     const SkRegion& getClip() const { return *fClip; }
getPaint() const263     const SkPaint* getPaint() const { return fPaint; }
264 private:
265     SkCanvas*       fCanvas;
266     const DeviceCM* fCurrLayer;
267     const SkPaint*  fPaint;     // May be null.
268     int             fLayerX;
269     int             fLayerY;
270     SkBool8         fSkipEmptyClips;
271 
272     typedef SkDraw INHERITED;
273 };
274 
275 /////////////////////////////////////////////////////////////////////////////
276 
277 class AutoDrawLooper {
278 public:
AutoDrawLooper(SkCanvas * canvas,const SkPaint & paint,SkDrawFilter::Type t)279     AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t)
280             : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) {
281         if ((fLooper = paint.getLooper()) != NULL) {
282             fLooper->init(canvas, (SkPaint*)&paint);
283         } else {
284             fOnce = true;
285         }
286         fFilter = canvas->getDrawFilter();
287         fNeedFilterRestore = false;
288     }
289 
~AutoDrawLooper()290     ~AutoDrawLooper() {
291         if (fNeedFilterRestore) {
292             SkASSERT(fFilter);
293             fFilter->restore(fCanvas, fPaint, fType);
294         }
295         if (NULL != fLooper) {
296             fLooper->restore();
297         }
298     }
299 
next()300     bool next() {
301         SkDrawFilter* filter = fFilter;
302 
303         // if we drew earlier with a filter, then we need to restore first
304         if (fNeedFilterRestore) {
305             SkASSERT(filter);
306             filter->restore(fCanvas, fPaint, fType);
307             fNeedFilterRestore = false;
308         }
309 
310         bool result;
311 
312         if (NULL != fLooper) {
313             result = fLooper->next();
314         } else {
315             result = fOnce;
316             fOnce = false;
317         }
318 
319         // if we're gonna draw, give the filter a chance to do its work
320         if (result && NULL != filter) {
321             fNeedFilterRestore = result = filter->filter(fCanvas, fPaint,
322                                                          fType);
323         }
324         return result;
325     }
326 
327 private:
328     SkDrawLooper*   fLooper;
329     SkDrawFilter*   fFilter;
330     SkCanvas*       fCanvas;
331     SkPaint*        fPaint;
332     SkDrawFilter::Type  fType;
333     bool            fOnce;
334     bool            fNeedFilterRestore;
335 
336 };
337 
338 /*  Stack helper for managing a SkBounder. In the destructor, if we were
339     given a bounder, we call its commit() method, signifying that we are
340     done accumulating bounds for that draw.
341 */
342 class SkAutoBounderCommit {
343 public:
SkAutoBounderCommit(SkBounder * bounder)344     SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
~SkAutoBounderCommit()345     ~SkAutoBounderCommit() {
346         if (NULL != fBounder) {
347             fBounder->commit();
348         }
349     }
350 private:
351     SkBounder*  fBounder;
352 };
353 
354 #include "SkColorPriv.h"
355 
356 class AutoValidator {
357 public:
AutoValidator(SkDevice * device)358     AutoValidator(SkDevice* device) : fDevice(device) {}
~AutoValidator()359     ~AutoValidator() {
360 #ifdef SK_DEBUG
361         const SkBitmap& bm = fDevice->accessBitmap(false);
362         if (bm.config() == SkBitmap::kARGB_4444_Config) {
363             for (int y = 0; y < bm.height(); y++) {
364                 const SkPMColor16* p = bm.getAddr16(0, y);
365                 for (int x = 0; x < bm.width(); x++) {
366                     SkPMColor16 c = p[x];
367                     SkPMColor16Assert(c);
368                 }
369             }
370         }
371 #endif
372     }
373 private:
374     SkDevice* fDevice;
375 };
376 
377 ////////// macros to place around the internal draw calls //////////////////
378 
379 #define ITER_BEGIN(paint, type)                                     \
380 /*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
381     AutoDrawLooper  looper(this, paint, type);                      \
382     while (looper.next()) {                                         \
383         SkAutoBounderCommit ac(fBounder);                           \
384         SkDrawIter          iter(this);
385 
386 #define ITER_END    }
387 
388 ////////////////////////////////////////////////////////////////////////////
389 
init(SkDevice * device)390 SkDevice* SkCanvas::init(SkDevice* device) {
391     fBounder = NULL;
392     fLocalBoundsCompareTypeDirty = true;
393     fLocalBoundsCompareTypeDirtyBW = true;
394     fLastDeviceToGainFocus = NULL;
395     fDeviceCMDirty = false;
396 
397     fMCRec = (MCRec*)fMCStack.push_back();
398     new (fMCRec) MCRec(NULL, 0);
399 
400     fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL));
401     fMCRec->fTopLayer = fMCRec->fLayer;
402     fMCRec->fNext = NULL;
403 
404     return this->setDevice(device);
405 }
406 
SkCanvas(SkDevice * device)407 SkCanvas::SkCanvas(SkDevice* device)
408         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
409     inc_canvas();
410 
411     this->init(device);
412 }
413 
SkCanvas(const SkBitmap & bitmap)414 SkCanvas::SkCanvas(const SkBitmap& bitmap)
415         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
416     inc_canvas();
417 
418     this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
419 }
420 
~SkCanvas()421 SkCanvas::~SkCanvas() {
422     // free up the contents of our deque
423     this->restoreToCount(1);    // restore everything but the last
424     this->internalRestore();    // restore the last, since we're going away
425 
426     fBounder->safeUnref();
427 
428     dec_canvas();
429 }
430 
setBounder(SkBounder * bounder)431 SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
432     SkRefCnt_SafeAssign(fBounder, bounder);
433     return bounder;
434 }
435 
getDrawFilter() const436 SkDrawFilter* SkCanvas::getDrawFilter() const {
437     return fMCRec->fFilter;
438 }
439 
setDrawFilter(SkDrawFilter * filter)440 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
441     SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
442     return filter;
443 }
444 
445 ///////////////////////////////////////////////////////////////////////////////
446 
getDevice() const447 SkDevice* SkCanvas::getDevice() const {
448     // return root device
449     SkDeque::Iter   iter(fMCStack);
450     MCRec*          rec = (MCRec*)iter.next();
451     SkASSERT(rec && rec->fLayer);
452     return rec->fLayer->fDevice;
453 }
454 
setDevice(SkDevice * device)455 SkDevice* SkCanvas::setDevice(SkDevice* device) {
456     // return root device
457     SkDeque::Iter   iter(fMCStack);
458     MCRec*          rec = (MCRec*)iter.next();
459     SkASSERT(rec && rec->fLayer);
460     SkDevice*       rootDevice = rec->fLayer->fDevice;
461 
462     if (rootDevice == device) {
463         return device;
464     }
465 
466     /* Notify the devices that they are going in/out of scope, so they can do
467        things like lock/unlock their pixels, etc.
468     */
469     if (device) {
470         device->lockPixels();
471     }
472     if (rootDevice) {
473         rootDevice->unlockPixels();
474     }
475 
476     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
477     rootDevice = device;
478 
479     fDeviceCMDirty = true;
480 
481     /*  Now we update our initial region to have the bounds of the new device,
482         and then intersect all of the clips in our stack with these bounds,
483         to ensure that we can't draw outside of the device's bounds (and trash
484                                                                      memory).
485 
486     NOTE: this is only a partial-fix, since if the new device is larger than
487         the previous one, we don't know how to "enlarge" the clips in our stack,
488         so drawing may be artificially restricted. Without keeping a history of
489         all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
490         reconstruct the correct clips, so this approximation will have to do.
491         The caller really needs to restore() back to the base if they want to
492         accurately take advantage of the new device bounds.
493     */
494 
495     if (NULL == device) {
496         rec->fRegion->setEmpty();
497         while ((rec = (MCRec*)iter.next()) != NULL) {
498             (void)rec->fRegion->setEmpty();
499         }
500     } else {
501         // compute our total bounds for all devices
502         SkIRect bounds;
503 
504         bounds.set(0, 0, device->width(), device->height());
505 
506         // now jam our 1st clip to be bounds, and intersect the rest with that
507         rec->fRegion->setRect(bounds);
508         while ((rec = (MCRec*)iter.next()) != NULL) {
509             (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op);
510         }
511     }
512     return device;
513 }
514 
setBitmapDevice(const SkBitmap & bitmap)515 SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
516     SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
517     device->unref();
518     return device;
519 }
520 
521 //////////////////////////////////////////////////////////////////////////////
522 
getViewport(SkIPoint * size) const523 bool SkCanvas::getViewport(SkIPoint* size) const {
524     return false;
525 }
526 
setViewport(int width,int height)527 bool SkCanvas::setViewport(int width, int height) {
528     return false;
529 }
530 
updateDeviceCMCache()531 void SkCanvas::updateDeviceCMCache() {
532     if (fDeviceCMDirty) {
533         const SkMatrix& totalMatrix = this->getTotalMatrix();
534         const SkRegion& totalClip = this->getTotalClip();
535         DeviceCM*       layer = fMCRec->fTopLayer;
536 
537         if (NULL == layer->fNext) {   // only one layer
538             layer->updateMC(totalMatrix, totalClip, NULL);
539         } else {
540             SkRegion clip;
541             clip = totalClip;  // make a copy
542             do {
543                 layer->updateMC(totalMatrix, clip, &clip);
544             } while ((layer = layer->fNext) != NULL);
545         }
546         fDeviceCMDirty = false;
547     }
548 }
549 
prepareForDeviceDraw(SkDevice * device)550 void SkCanvas::prepareForDeviceDraw(SkDevice* device) {
551     SkASSERT(device);
552     if (fLastDeviceToGainFocus != device) {
553         device->gainFocus(this);
554         fLastDeviceToGainFocus = device;
555     }
556 }
557 
558 ///////////////////////////////////////////////////////////////////////////////
559 
internalSave(SaveFlags flags)560 int SkCanvas::internalSave(SaveFlags flags) {
561     int saveCount = this->getSaveCount(); // record this before the actual save
562 
563     MCRec* newTop = (MCRec*)fMCStack.push_back();
564     new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
565 
566     newTop->fNext = fMCRec;
567     fMCRec = newTop;
568 
569     return saveCount;
570 }
571 
save(SaveFlags flags)572 int SkCanvas::save(SaveFlags flags) {
573     // call shared impl
574     return this->internalSave(flags);
575 }
576 
577 #define C32MASK (1 << SkBitmap::kARGB_8888_Config)
578 #define C16MASK (1 << SkBitmap::kRGB_565_Config)
579 #define C8MASK  (1 << SkBitmap::kA8_Config)
580 
resolve_config(SkCanvas * canvas,const SkIRect & bounds,SkCanvas::SaveFlags flags,bool * isOpaque)581 static SkBitmap::Config resolve_config(SkCanvas* canvas,
582                                        const SkIRect& bounds,
583                                        SkCanvas::SaveFlags flags,
584                                        bool* isOpaque) {
585     *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
586 
587 #if 0
588     // loop through and union all the configs we may draw into
589     uint32_t configMask = 0;
590     for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
591     {
592         SkDevice* device = canvas->getLayerDevice(i);
593         if (device->intersects(bounds))
594             configMask |= 1 << device->config();
595     }
596 
597     // if the caller wants alpha or fullcolor, we can't return 565
598     if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
599                  SkCanvas::kHasAlphaLayer_SaveFlag))
600         configMask &= ~C16MASK;
601 
602     switch (configMask) {
603     case C8MASK:    // if we only have A8, return that
604         return SkBitmap::kA8_Config;
605 
606     case C16MASK:   // if we only have 565, return that
607         return SkBitmap::kRGB_565_Config;
608 
609     default:
610         return SkBitmap::kARGB_8888_Config; // default answer
611     }
612 #else
613     return SkBitmap::kARGB_8888_Config; // default answer
614 #endif
615 }
616 
bounds_affects_clip(SkCanvas::SaveFlags flags)617 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
618     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
619 }
620 
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)621 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
622                         SaveFlags flags) {
623     // do this before we create the layer. We don't call the public save() since
624     // that would invoke a possibly overridden virtual
625     int count = this->internalSave(flags);
626 
627     fDeviceCMDirty = true;
628 
629     SkIRect         ir;
630     const SkIRect&  clipBounds = this->getTotalClip().getBounds();
631 
632     if (NULL != bounds) {
633         SkRect r;
634 
635         this->getTotalMatrix().mapRect(&r, *bounds);
636         r.roundOut(&ir);
637         // early exit if the layer's bounds are clipped out
638         if (!ir.intersect(clipBounds)) {
639             if (bounds_affects_clip(flags))
640                 fMCRec->fRegion->setEmpty();
641             return count;
642         }
643     } else {    // no user bounds, so just use the clip
644         ir = clipBounds;
645     }
646 
647     // early exit if the clip is now empty
648     if (bounds_affects_clip(flags) &&
649         !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) {
650         return count;
651     }
652 
653     bool isOpaque;
654     SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
655 
656     SkDevice* device = this->createDevice(config, ir.width(), ir.height(),
657                                           isOpaque, true);
658     DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
659     device->unref();
660 
661     layer->fNext = fMCRec->fTopLayer;
662     fMCRec->fLayer = layer;
663     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
664 
665     return count;
666 }
667 
saveLayerAlpha(const SkRect * bounds,U8CPU alpha,SaveFlags flags)668 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
669                              SaveFlags flags) {
670     if (0xFF == alpha) {
671         return this->saveLayer(bounds, NULL, flags);
672     } else {
673         SkPaint tmpPaint;
674         tmpPaint.setAlpha(alpha);
675         return this->saveLayer(bounds, &tmpPaint, flags);
676     }
677 }
678 
restore()679 void SkCanvas::restore() {
680     // check for underflow
681     if (fMCStack.count() > 1) {
682         this->internalRestore();
683     }
684 }
685 
internalRestore()686 void SkCanvas::internalRestore() {
687     SkASSERT(fMCStack.count() != 0);
688 
689     fDeviceCMDirty = true;
690     fLocalBoundsCompareTypeDirty = true;
691     fLocalBoundsCompareTypeDirtyBW = true;
692 
693 	// reserve our layer (if any)
694     DeviceCM* layer = fMCRec->fLayer;   // may be null
695     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
696     fMCRec->fLayer = NULL;
697 
698     // now do the normal restore()
699     fMCRec->~MCRec();       // balanced in save()
700     fMCStack.pop_back();
701     fMCRec = (MCRec*)fMCStack.back();
702 
703     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
704         since if we're being recorded, we don't want to record this (the
705         recorder will have already recorded the restore).
706     */
707     if (NULL != layer) {
708         if (layer->fNext) {
709             this->drawDevice(layer->fDevice, layer->fX, layer->fY,
710                              layer->fPaint);
711             // reset this, since drawDevice will have set it to true
712             fDeviceCMDirty = true;
713         }
714         SkDELETE(layer);
715 	}
716 }
717 
getSaveCount() const718 int SkCanvas::getSaveCount() const {
719     return fMCStack.count();
720 }
721 
restoreToCount(int count)722 void SkCanvas::restoreToCount(int count) {
723     // sanity check
724     if (count < 1) {
725         count = 1;
726     }
727     while (fMCStack.count() > count) {
728         this->restore();
729     }
730 }
731 
732 /////////////////////////////////////////////////////////////////////////////
733 
734 // can't draw it if its empty, or its too big for a fixed-point width or height
reject_bitmap(const SkBitmap & bitmap)735 static bool reject_bitmap(const SkBitmap& bitmap) {
736     return  bitmap.width() <= 0 || bitmap.height() <= 0 ||
737             bitmap.width() > 32767 || bitmap.height() > 32767;
738 }
739 
internalDrawBitmap(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)740 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
741                                 const SkMatrix& matrix, const SkPaint* paint) {
742     if (reject_bitmap(bitmap)) {
743         return;
744     }
745 
746     if (NULL == paint) {
747         SkPaint tmpPaint;
748         this->commonDrawBitmap(bitmap, matrix, tmpPaint);
749     } else {
750         this->commonDrawBitmap(bitmap, matrix, *paint);
751     }
752 }
753 
drawDevice(SkDevice * device,int x,int y,const SkPaint * paint)754 void SkCanvas::drawDevice(SkDevice* device, int x, int y,
755                           const SkPaint* paint) {
756     SkPaint tmp;
757     if (NULL == paint) {
758         tmp.setDither(true);
759         paint = &tmp;
760     }
761 
762     ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
763     while (iter.next()) {
764         iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
765                                  *paint);
766     }
767     ITER_END
768 }
769 
770 /////////////////////////////////////////////////////////////////////////////
771 
translate(SkScalar dx,SkScalar dy)772 bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
773     fDeviceCMDirty = true;
774     fLocalBoundsCompareTypeDirty = true;
775     fLocalBoundsCompareTypeDirtyBW = true;
776     return fMCRec->fMatrix->preTranslate(dx, dy);
777 }
778 
scale(SkScalar sx,SkScalar sy)779 bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
780     fDeviceCMDirty = true;
781     fLocalBoundsCompareTypeDirty = true;
782     fLocalBoundsCompareTypeDirtyBW = true;
783     return fMCRec->fMatrix->preScale(sx, sy);
784 }
785 
rotate(SkScalar degrees)786 bool SkCanvas::rotate(SkScalar degrees) {
787     fDeviceCMDirty = true;
788     fLocalBoundsCompareTypeDirty = true;
789     fLocalBoundsCompareTypeDirtyBW = true;
790     return fMCRec->fMatrix->preRotate(degrees);
791 }
792 
skew(SkScalar sx,SkScalar sy)793 bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
794     fDeviceCMDirty = true;
795     fLocalBoundsCompareTypeDirty = true;
796     fLocalBoundsCompareTypeDirtyBW = true;
797     return fMCRec->fMatrix->preSkew(sx, sy);
798 }
799 
concat(const SkMatrix & matrix)800 bool SkCanvas::concat(const SkMatrix& matrix) {
801     fDeviceCMDirty = true;
802     fLocalBoundsCompareTypeDirty = true;
803     fLocalBoundsCompareTypeDirtyBW = true;
804     return fMCRec->fMatrix->preConcat(matrix);
805 }
806 
setMatrix(const SkMatrix & matrix)807 void SkCanvas::setMatrix(const SkMatrix& matrix) {
808     fDeviceCMDirty = true;
809     fLocalBoundsCompareTypeDirty = true;
810     fLocalBoundsCompareTypeDirtyBW = true;
811     *fMCRec->fMatrix = matrix;
812 }
813 
814 // this is not virtual, so it must call a virtual method so that subclasses
815 // will see its action
resetMatrix()816 void SkCanvas::resetMatrix() {
817     SkMatrix matrix;
818 
819     matrix.reset();
820     this->setMatrix(matrix);
821 }
822 
823 //////////////////////////////////////////////////////////////////////////////
824 
clipRect(const SkRect & rect,SkRegion::Op op)825 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
826     fDeviceCMDirty = true;
827     fLocalBoundsCompareTypeDirty = true;
828     fLocalBoundsCompareTypeDirtyBW = true;
829 
830     if (fMCRec->fMatrix->rectStaysRect()) {
831         // for these simpler matrices, we can stay a rect ever after applying
832         // the matrix. This means we don't have to a) make a path, and b) tell
833         // the region code to scan-convert the path, only to discover that it
834         // is really just a rect.
835         SkRect      r;
836         SkIRect     ir;
837 
838         fMCRec->fMatrix->mapRect(&r, rect);
839         r.round(&ir);
840         return fMCRec->fRegion->op(ir, op);
841     } else {
842         // since we're rotate or some such thing, we convert the rect to a path
843         // and clip against that, since it can handle any matrix. However, to
844         // avoid recursion in the case where we are subclassed (e.g. Pictures)
845         // we explicitly call "our" version of clipPath.
846         SkPath  path;
847 
848         path.addRect(rect);
849         return this->SkCanvas::clipPath(path, op);
850     }
851 }
852 
clipPath(const SkPath & path,SkRegion::Op op)853 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
854     fDeviceCMDirty = true;
855     fLocalBoundsCompareTypeDirty = true;
856     fLocalBoundsCompareTypeDirtyBW = true;
857 
858     SkPath devPath;
859     path.transform(*fMCRec->fMatrix, &devPath);
860 
861     if (SkRegion::kIntersect_Op == op) {
862         return fMCRec->fRegion->setPath(devPath, *fMCRec->fRegion);
863     } else {
864         SkRegion base;
865         const SkBitmap& bm = this->getDevice()->accessBitmap(false);
866         base.setRect(0, 0, bm.width(), bm.height());
867 
868         if (SkRegion::kReplace_Op == op) {
869             return fMCRec->fRegion->setPath(devPath, base);
870         } else {
871             SkRegion rgn;
872             rgn.setPath(devPath, base);
873             return fMCRec->fRegion->op(rgn, op);
874         }
875     }
876 }
877 
clipRegion(const SkRegion & rgn,SkRegion::Op op)878 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
879     fDeviceCMDirty = true;
880     fLocalBoundsCompareTypeDirty = true;
881     fLocalBoundsCompareTypeDirtyBW = true;
882 
883     return fMCRec->fRegion->op(rgn, op);
884 }
885 
computeLocalClipBoundsCompareType(EdgeType et) const886 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
887     SkRect r;
888     SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType :
889             fLocalBoundsCompareTypeBW;
890 
891     if (!this->getClipBounds(&r, et)) {
892         rCompare.setEmpty();
893     } else {
894         rCompare.set(SkScalarToCompareType(r.fLeft),
895                      SkScalarToCompareType(r.fTop),
896                      SkScalarToCompareType(r.fRight),
897                      SkScalarToCompareType(r.fBottom));
898     }
899 }
900 
901 /*  current impl ignores edgetype, and relies on
902     getLocalClipBoundsCompareType(), which always returns a value assuming
903     antialiasing (worst case)
904  */
quickReject(const SkRect & rect,EdgeType et) const905 bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
906     if (fMCRec->fRegion->isEmpty()) {
907         return true;
908     }
909 
910     if (fMCRec->fMatrix->getType() & SkMatrix::kPerspective_Mask) {
911         SkRect dst;
912         fMCRec->fMatrix->mapRect(&dst, rect);
913         SkIRect idst;
914         dst.roundOut(&idst);
915         return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds());
916     } else {
917         const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et);
918 
919         // for speed, do the most likely reject compares first
920         SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
921         SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
922         if (userT >= clipR.fBottom || userB <= clipR.fTop) {
923             return true;
924         }
925         SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
926         SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
927         if (userL >= clipR.fRight || userR <= clipR.fLeft) {
928             return true;
929         }
930         return false;
931     }
932 }
933 
quickReject(const SkPath & path,EdgeType et) const934 bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
935     return path.isEmpty() || this->quickReject(path.getBounds(), et);
936 }
937 
quickRejectY(SkScalar top,SkScalar bottom,EdgeType et) const938 bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
939     /*  current impl ignores edgetype, and relies on
940         getLocalClipBoundsCompareType(), which always returns a value assuming
941         antialiasing (worst case)
942      */
943 
944     if (fMCRec->fRegion->isEmpty()) {
945         return true;
946     }
947 
948     SkScalarCompareType userT = SkScalarToCompareType(top);
949     SkScalarCompareType userB = SkScalarToCompareType(bottom);
950 
951     // check for invalid user Y coordinates (i.e. empty)
952     // reed: why do we need to do this check, since it slows us down?
953     if (userT >= userB) {
954         return true;
955     }
956 
957     // check if we are above or below the local clip bounds
958     const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
959     return userT >= clipR.fBottom || userB <= clipR.fTop;
960 }
961 
getClipBounds(SkRect * bounds,EdgeType et) const962 bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
963     const SkRegion& clip = *fMCRec->fRegion;
964     if (clip.isEmpty()) {
965         if (bounds) {
966             bounds->setEmpty();
967         }
968         return false;
969     }
970 
971     SkMatrix inverse;
972     // if we can't invert the CTM, we can't return local clip bounds
973     if (!fMCRec->fMatrix->invert(&inverse)) {
974         if (bounds) {
975             bounds->setEmpty();
976         }
977         return false;
978     }
979 
980     if (NULL != bounds) {
981         SkRect   r;
982         // get the clip's bounds
983         const SkIRect& ibounds = clip.getBounds();
984         // adjust it outwards if we are antialiasing
985         int inset = (kAA_EdgeType == et);
986         r.iset(ibounds.fLeft - inset,  ibounds.fTop - inset,
987                ibounds.fRight + inset, ibounds.fBottom + inset);
988 
989         // invert into local coordinates
990         inverse.mapRect(bounds, r);
991     }
992     return true;
993 }
994 
getTotalMatrix() const995 const SkMatrix& SkCanvas::getTotalMatrix() const {
996     return *fMCRec->fMatrix;
997 }
998 
getTotalClip() const999 const SkRegion& SkCanvas::getTotalClip() const {
1000     return *fMCRec->fRegion;
1001 }
1002 
1003 ///////////////////////////////////////////////////////////////////////////////
1004 
createDevice(SkBitmap::Config config,int width,int height,bool isOpaque,bool isForLayer)1005 SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
1006                                  int height, bool isOpaque, bool isForLayer) {
1007     SkBitmap bitmap;
1008 
1009     bitmap.setConfig(config, width, height);
1010     bitmap.setIsOpaque(isOpaque);
1011 
1012     // should this happen in the device subclass?
1013     bitmap.allocPixels();
1014     if (!bitmap.isOpaque()) {
1015         bitmap.eraseARGB(0, 0, 0, 0);
1016     }
1017 
1018     return SkNEW_ARGS(SkDevice, (bitmap));
1019 }
1020 
1021 //////////////////////////////////////////////////////////////////////////////
1022 //  These are the virtual drawing methods
1023 //////////////////////////////////////////////////////////////////////////////
1024 
drawPaint(const SkPaint & paint)1025 void SkCanvas::drawPaint(const SkPaint& paint) {
1026     ITER_BEGIN(paint, SkDrawFilter::kPaint_Type)
1027 
1028     while (iter.next()) {
1029         iter.fDevice->drawPaint(iter, paint);
1030     }
1031 
1032     ITER_END
1033 }
1034 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1035 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1036                           const SkPaint& paint) {
1037     if ((long)count <= 0) {
1038         return;
1039     }
1040 
1041     SkASSERT(pts != NULL);
1042 
1043     ITER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1044 
1045     while (iter.next()) {
1046         iter.fDevice->drawPoints(iter, mode, count, pts, paint);
1047     }
1048 
1049     ITER_END
1050 }
1051 
drawRect(const SkRect & r,const SkPaint & paint)1052 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1053     if (paint.canComputeFastBounds()) {
1054         SkRect storage;
1055         if (this->quickReject(paint.computeFastBounds(r, &storage),
1056                               paint2EdgeType(&paint))) {
1057             return;
1058         }
1059     }
1060 
1061     ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
1062 
1063     while (iter.next()) {
1064         iter.fDevice->drawRect(iter, r, paint);
1065     }
1066 
1067     ITER_END
1068 }
1069 
drawPath(const SkPath & path,const SkPaint & paint)1070 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1071     if (paint.canComputeFastBounds()) {
1072         SkRect storage;
1073         const SkRect& bounds = path.getBounds();
1074         if (this->quickReject(paint.computeFastBounds(bounds, &storage),
1075                               paint2EdgeType(&paint))) {
1076             return;
1077         }
1078     }
1079 
1080     ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
1081 
1082     while (iter.next()) {
1083         iter.fDevice->drawPath(iter, path, paint);
1084     }
1085 
1086     ITER_END
1087 }
1088 
drawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)1089 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1090                           const SkPaint* paint) {
1091     SkDEBUGCODE(bitmap.validate();)
1092 
1093     if (NULL == paint || (paint->getMaskFilter() == NULL)) {
1094         SkRect fastBounds;
1095         fastBounds.set(x, y,
1096                        x + SkIntToScalar(bitmap.width()),
1097                        y + SkIntToScalar(bitmap.height()));
1098         if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
1099             return;
1100         }
1101     }
1102 
1103     SkMatrix matrix;
1104     matrix.setTranslate(x, y);
1105     this->internalDrawBitmap(bitmap, matrix, paint);
1106 }
1107 
drawBitmapRect(const SkBitmap & bitmap,const SkIRect * src,const SkRect & dst,const SkPaint * paint)1108 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
1109                               const SkRect& dst, const SkPaint* paint) {
1110     if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1111         return;
1112     }
1113 
1114     // do this now, to avoid the cost of calling extract for RLE bitmaps
1115     if (this->quickReject(dst, paint2EdgeType(paint))) {
1116         return;
1117     }
1118 
1119     SkBitmap        tmp;    // storage if we need a subset of bitmap
1120     const SkBitmap* bitmapPtr = &bitmap;
1121 
1122     if (NULL != src) {
1123         if (!bitmap.extractSubset(&tmp, *src)) {
1124             return;     // extraction failed
1125         }
1126         bitmapPtr = &tmp;
1127     }
1128 
1129     SkMatrix matrix;
1130     SkRect tmpSrc;
1131     if (src) {
1132         tmpSrc.set(*src);
1133         // if the extract process clipped off the top or left of the
1134         // original, we adjust for that here to get the position right.
1135         if (tmpSrc.fLeft > 0) {
1136             tmpSrc.fRight -= tmpSrc.fLeft;
1137             tmpSrc.fLeft = 0;
1138         }
1139         if (tmpSrc.fTop > 0) {
1140             tmpSrc.fBottom -= tmpSrc.fTop;
1141             tmpSrc.fTop = 0;
1142         }
1143     } else {
1144         tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()),
1145                    SkIntToScalar(bitmap.height()));
1146     }
1147     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1148     this->internalDrawBitmap(*bitmapPtr, matrix, paint);
1149 }
1150 
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)1151 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1152                                 const SkPaint* paint) {
1153     SkDEBUGCODE(bitmap.validate();)
1154     this->internalDrawBitmap(bitmap, matrix, paint);
1155 }
1156 
commonDrawBitmap(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint & paint)1157 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
1158                                 const SkPaint& paint) {
1159     SkDEBUGCODE(bitmap.validate();)
1160 
1161     ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1162 
1163     while (iter.next()) {
1164         iter.fDevice->drawBitmap(iter, bitmap, matrix, paint);
1165     }
1166 
1167     ITER_END
1168 }
1169 
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint * paint)1170 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1171                           const SkPaint* paint) {
1172     SkDEBUGCODE(bitmap.validate();)
1173 
1174     if (reject_bitmap(bitmap)) {
1175         return;
1176     }
1177 
1178     SkPaint tmp;
1179     if (NULL == paint) {
1180         paint = &tmp;
1181     }
1182 
1183     ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1184 
1185     while (iter.next()) {
1186         iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
1187                                  *paint);
1188     }
1189     ITER_END
1190 }
1191 
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)1192 void SkCanvas::drawText(const void* text, size_t byteLength,
1193                         SkScalar x, SkScalar y, const SkPaint& paint) {
1194     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1195 
1196     while (iter.next()) {
1197         iter.fDevice->drawText(iter, text, byteLength, x, y, paint);
1198     }
1199 
1200     ITER_END
1201 }
1202 
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)1203 void SkCanvas::drawPosText(const void* text, size_t byteLength,
1204                            const SkPoint pos[], const SkPaint& paint) {
1205     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1206 
1207     while (iter.next()) {
1208         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1209                                   paint);
1210     }
1211 
1212     ITER_END
1213 }
1214 
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)1215 void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1216                             const SkScalar xpos[], SkScalar constY,
1217                             const SkPaint& paint) {
1218     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1219 
1220     while (iter.next()) {
1221         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1222                                   paint);
1223     }
1224 
1225     ITER_END
1226 }
1227 
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)1228 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1229                               const SkPath& path, const SkMatrix* matrix,
1230                               const SkPaint& paint) {
1231     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1232 
1233     while (iter.next()) {
1234         iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1235                                      matrix, paint);
1236     }
1237 
1238     ITER_END
1239 }
1240 
drawPosTextOnPath(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint,const SkPath & path,const SkMatrix * matrix)1241 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
1242                                  const SkPoint pos[], const SkPaint& paint,
1243                                  const SkPath& path, const SkMatrix* matrix) {
1244 
1245     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1246 
1247     while (iter.next()) {
1248         iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
1249                                         paint, path, matrix);
1250     }
1251 
1252     ITER_END
1253 }
1254 
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)1255 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1256                             const SkPoint verts[], const SkPoint texs[],
1257                             const SkColor colors[], SkXfermode* xmode,
1258                             const uint16_t indices[], int indexCount,
1259                             const SkPaint& paint) {
1260     ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
1261 
1262     while (iter.next()) {
1263         iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1264                                    colors, xmode, indices, indexCount, paint);
1265     }
1266 
1267     ITER_END
1268 }
1269 
drawData(const void * data,size_t length)1270 void SkCanvas::drawData(const void* data, size_t length) {
1271     // do nothing. Subclasses may do something with the data
1272 }
1273 
1274 //////////////////////////////////////////////////////////////////////////////
1275 // These methods are NOT virtual, and therefore must call back into virtual
1276 // methods, rather than actually drawing themselves.
1277 //////////////////////////////////////////////////////////////////////////////
1278 
drawARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b,SkXfermode::Mode mode)1279 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1280                         SkXfermode::Mode mode) {
1281     SkPaint paint;
1282 
1283     paint.setARGB(a, r, g, b);
1284     if (SkXfermode::kSrcOver_Mode != mode) {
1285         paint.setXfermodeMode(mode);
1286     }
1287     this->drawPaint(paint);
1288 }
1289 
drawColor(SkColor c,SkXfermode::Mode mode)1290 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
1291     SkPaint paint;
1292 
1293     paint.setColor(c);
1294     if (SkXfermode::kSrcOver_Mode != mode) {
1295         paint.setXfermodeMode(mode);
1296     }
1297     this->drawPaint(paint);
1298 }
1299 
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)1300 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
1301     SkPoint pt;
1302 
1303     pt.set(x, y);
1304     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1305 }
1306 
drawPoint(SkScalar x,SkScalar y,SkColor color)1307 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
1308     SkPoint pt;
1309     SkPaint paint;
1310 
1311     pt.set(x, y);
1312     paint.setColor(color);
1313     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1314 }
1315 
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)1316 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
1317                         const SkPaint& paint) {
1318     SkPoint pts[2];
1319 
1320     pts[0].set(x0, y0);
1321     pts[1].set(x1, y1);
1322     this->drawPoints(kLines_PointMode, 2, pts, paint);
1323 }
1324 
drawRectCoords(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom,const SkPaint & paint)1325 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
1326                               SkScalar right, SkScalar bottom,
1327                               const SkPaint& paint) {
1328     SkRect  r;
1329 
1330     r.set(left, top, right, bottom);
1331     this->drawRect(r, paint);
1332 }
1333 
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)1334 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
1335                           const SkPaint& paint) {
1336     if (radius < 0) {
1337         radius = 0;
1338     }
1339 
1340     SkRect  r;
1341     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
1342 
1343     if (paint.canComputeFastBounds()) {
1344         SkRect storage;
1345         if (this->quickReject(paint.computeFastBounds(r, &storage),
1346                               paint2EdgeType(&paint))) {
1347             return;
1348         }
1349     }
1350 
1351     SkPath  path;
1352     path.addOval(r);
1353     this->drawPath(path, paint);
1354 }
1355 
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)1356 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
1357                              const SkPaint& paint) {
1358     if (rx > 0 && ry > 0) {
1359         if (paint.canComputeFastBounds()) {
1360             SkRect storage;
1361             if (this->quickReject(paint.computeFastBounds(r, &storage),
1362                                   paint2EdgeType(&paint))) {
1363                 return;
1364             }
1365         }
1366 
1367         SkPath  path;
1368         path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
1369         this->drawPath(path, paint);
1370     } else {
1371         this->drawRect(r, paint);
1372     }
1373 }
1374 
drawOval(const SkRect & oval,const SkPaint & paint)1375 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1376     if (paint.canComputeFastBounds()) {
1377         SkRect storage;
1378         if (this->quickReject(paint.computeFastBounds(oval, &storage),
1379                               paint2EdgeType(&paint))) {
1380             return;
1381         }
1382     }
1383 
1384     SkPath  path;
1385     path.addOval(oval);
1386     this->drawPath(path, paint);
1387 }
1388 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)1389 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
1390                        SkScalar sweepAngle, bool useCenter,
1391                        const SkPaint& paint) {
1392     if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
1393         this->drawOval(oval, paint);
1394     } else {
1395         SkPath  path;
1396         if (useCenter) {
1397             path.moveTo(oval.centerX(), oval.centerY());
1398         }
1399         path.arcTo(oval, startAngle, sweepAngle, !useCenter);
1400         if (useCenter) {
1401             path.close();
1402         }
1403         this->drawPath(path, paint);
1404     }
1405 }
1406 
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)1407 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
1408                                 const SkPath& path, SkScalar hOffset,
1409                                 SkScalar vOffset, const SkPaint& paint) {
1410     SkMatrix    matrix;
1411 
1412     matrix.setTranslate(hOffset, vOffset);
1413     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
1414 }
1415 
1416 ///////////////////////////////////////////////////////////////////////////////
1417 
drawPicture(SkPicture & picture)1418 void SkCanvas::drawPicture(SkPicture& picture) {
1419     int saveCount = save();
1420     picture.draw(this);
1421     restoreToCount(saveCount);
1422 }
1423 
drawShape(SkShape * shape)1424 void SkCanvas::drawShape(SkShape* shape) {
1425     // shape baseclass takes care of save/restore
1426     shape->draw(this);
1427 }
1428 
1429 ///////////////////////////////////////////////////////////////////////////////
1430 ///////////////////////////////////////////////////////////////////////////////
1431 
LayerIter(SkCanvas * canvas,bool skipEmptyClips)1432 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
1433     // need COMPILE_TIME_ASSERT
1434     SkASSERT(sizeof(fStorage) >= sizeof(SkDrawIter));
1435 
1436     SkASSERT(canvas);
1437 
1438     fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
1439     fDone = !fImpl->next();
1440 }
1441 
~LayerIter()1442 SkCanvas::LayerIter::~LayerIter() {
1443     fImpl->~SkDrawIter();
1444 }
1445 
next()1446 void SkCanvas::LayerIter::next() {
1447     fDone = !fImpl->next();
1448 }
1449 
device() const1450 SkDevice* SkCanvas::LayerIter::device() const {
1451     return fImpl->getDevice();
1452 }
1453 
matrix() const1454 const SkMatrix& SkCanvas::LayerIter::matrix() const {
1455     return fImpl->getMatrix();
1456 }
1457 
paint() const1458 const SkPaint& SkCanvas::LayerIter::paint() const {
1459     const SkPaint* paint = fImpl->getPaint();
1460     if (NULL == paint) {
1461         paint = &fDefaultPaint;
1462     }
1463     return *paint;
1464 }
1465 
clip() const1466 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
x() const1467 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const1468 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
1469 
1470