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