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