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