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