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