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