SkCanvas.cpp revision 971aca75572ed6e0c5e1cc959173dc58ca7b6b8d
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 "SkBounder.h"
12#include "SkDevice.h"
13#include "SkDeviceImageFilterProxy.h"
14#include "SkDraw.h"
15#include "SkDrawFilter.h"
16#include "SkDrawLooper.h"
17#include "SkMetaData.h"
18#include "SkPicture.h"
19#include "SkRasterClip.h"
20#include "SkScalarCompare.h"
21#include "SkSurface_Base.h"
22#include "SkTemplates.h"
23#include "SkTextFormatParams.h"
24#include "SkTLazy.h"
25#include "SkUtils.h"
26
27SK_DEFINE_INST_COUNT(SkBounder)
28SK_DEFINE_INST_COUNT(SkCanvas)
29SK_DEFINE_INST_COUNT(SkDrawFilter)
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(this);
62    }
63}
64
65///////////////////////////////////////////////////////////////////////////////
66
67/*  This is the record we keep for each SkDevice 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    SkDevice*           fDevice;
77    SkRasterClip        fClip;
78    const SkMatrix*     fMatrix;
79    SkPaint*            fPaint; // may be null (in the future)
80
81    DeviceCM(SkDevice* 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    MCRec*          fNext;
152    SkMatrix*       fMatrix;        // points to either fMatrixStorage or prev MCRec
153    SkRasterClip*   fRasterClip;    // points to either fRegionStorage or prev MCRec
154    SkDrawFilter*   fFilter;        // the current filter (or null)
155
156    DeviceCM*   fLayer;
157    /*  If there are any layers in the stack, this points to the top-most
158        one that is at or below this level in the stack (so we know what
159        bitmap/device to draw into from this level. This value is NOT
160        reference counted, since the real owner is either our fLayer field,
161        or a previous one in a lower level.)
162    */
163    DeviceCM*   fTopLayer;
164
165    MCRec(const MCRec* prev, int flags) {
166        if (NULL != prev) {
167            if (flags & SkCanvas::kMatrix_SaveFlag) {
168                fMatrixStorage = *prev->fMatrix;
169                fMatrix = &fMatrixStorage;
170            } else {
171                fMatrix = prev->fMatrix;
172            }
173
174            if (flags & SkCanvas::kClip_SaveFlag) {
175                fRasterClipStorage = *prev->fRasterClip;
176                fRasterClip = &fRasterClipStorage;
177            } else {
178                fRasterClip = prev->fRasterClip;
179            }
180
181            fFilter = prev->fFilter;
182            SkSafeRef(fFilter);
183
184            fTopLayer = prev->fTopLayer;
185        } else {   // no prev
186            fMatrixStorage.reset();
187
188            fMatrix     = &fMatrixStorage;
189            fRasterClip = &fRasterClipStorage;
190            fFilter     = NULL;
191            fTopLayer   = NULL;
192        }
193        fLayer = NULL;
194
195        // don't bother initializing fNext
196        inc_rec();
197    }
198    ~MCRec() {
199        SkSafeUnref(fFilter);
200        SkDELETE(fLayer);
201        dec_rec();
202    }
203
204private:
205    SkMatrix        fMatrixStorage;
206    SkRasterClip    fRasterClipStorage;
207};
208
209class SkDrawIter : public SkDraw {
210public:
211    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
212        canvas = canvas->canvasForDrawIter();
213        fCanvas = canvas;
214        canvas->updateDeviceCMCache();
215
216        fClipStack = &canvas->fClipStack;
217        fBounder = canvas->getBounder();
218        fCurrLayer = canvas->fMCRec->fTopLayer;
219        fSkipEmptyClips = skipEmptyClips;
220    }
221
222    bool next() {
223        // skip over recs with empty clips
224        if (fSkipEmptyClips) {
225            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
226                fCurrLayer = fCurrLayer->fNext;
227            }
228        }
229
230        const DeviceCM* rec = fCurrLayer;
231        if (rec && rec->fDevice) {
232
233            fMatrix = rec->fMatrix;
234            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
235            fRC     = &rec->fClip;
236            fDevice = rec->fDevice;
237            fBitmap = &fDevice->accessBitmap(true);
238            fPaint  = rec->fPaint;
239            SkDEBUGCODE(this->validate();)
240
241            fCurrLayer = rec->fNext;
242            if (fBounder) {
243                fBounder->setClip(fClip);
244            }
245            // fCurrLayer may be NULL now
246
247            return true;
248        }
249        return false;
250    }
251
252    SkDevice* getDevice() const { return fDevice; }
253    int getX() const { return fDevice->getOrigin().x(); }
254    int getY() const { return fDevice->getOrigin().y(); }
255    const SkMatrix& getMatrix() const { return *fMatrix; }
256    const SkRegion& getClip() const { return *fClip; }
257    const SkPaint* getPaint() const { return fPaint; }
258
259private:
260    SkCanvas*       fCanvas;
261    const DeviceCM* fCurrLayer;
262    const SkPaint*  fPaint;     // May be null.
263    SkBool8         fSkipEmptyClips;
264
265    typedef SkDraw INHERITED;
266};
267
268/////////////////////////////////////////////////////////////////////////////
269
270class AutoDrawLooper {
271public:
272    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
273                   bool skipLayerForImageFilter = false) : fOrigPaint(paint) {
274        fCanvas = canvas;
275        fLooper = paint.getLooper();
276        fFilter = canvas->getDrawFilter();
277        fPaint = NULL;
278        fSaveCount = canvas->getSaveCount();
279        fDoClearImageFilter = false;
280        fDone = false;
281
282        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
283            SkPaint tmp;
284            tmp.setImageFilter(fOrigPaint.getImageFilter());
285            // it would be nice if we had a guess at the bounds, instead of null
286            (void)canvas->internalSaveLayer(NULL, &tmp,
287                                    SkCanvas::kARGB_ClipLayer_SaveFlag, true);
288            // we'll clear the imageFilter for the actual draws in next(), so
289            // it will only be applied during the restore().
290            fDoClearImageFilter = true;
291        }
292
293        if (fLooper) {
294            fLooper->init(canvas);
295            fIsSimple = false;
296        } else {
297            // can we be marked as simple?
298            fIsSimple = !fFilter && !fDoClearImageFilter;
299        }
300    }
301
302    ~AutoDrawLooper() {
303        if (fDoClearImageFilter) {
304            fCanvas->internalRestore();
305        }
306        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
307    }
308
309    const SkPaint& paint() const {
310        SkASSERT(fPaint);
311        return *fPaint;
312    }
313
314    bool next(SkDrawFilter::Type drawType) {
315        if (fDone) {
316            return false;
317        } else if (fIsSimple) {
318            fDone = true;
319            fPaint = &fOrigPaint;
320            return !fPaint->nothingToDraw();
321        } else {
322            return this->doNext(drawType);
323        }
324    }
325
326private:
327    SkLazyPaint     fLazyPaint;
328    SkCanvas*       fCanvas;
329    const SkPaint&  fOrigPaint;
330    SkDrawLooper*   fLooper;
331    SkDrawFilter*   fFilter;
332    const SkPaint*  fPaint;
333    int             fSaveCount;
334    bool            fDoClearImageFilter;
335    bool            fDone;
336    bool            fIsSimple;
337
338    bool doNext(SkDrawFilter::Type drawType);
339};
340
341bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
342    fPaint = NULL;
343    SkASSERT(!fIsSimple);
344    SkASSERT(fLooper || fFilter || fDoClearImageFilter);
345
346    SkPaint* paint = fLazyPaint.set(fOrigPaint);
347
348    if (fDoClearImageFilter) {
349        paint->setImageFilter(NULL);
350    }
351
352    if (fLooper && !fLooper->next(fCanvas, paint)) {
353        fDone = true;
354        return false;
355    }
356    if (fFilter) {
357        if (!fFilter->filter(paint, drawType)) {
358            fDone = true;
359            return false;
360        }
361        if (NULL == fLooper) {
362            // no looper means we only draw once
363            fDone = true;
364        }
365    }
366    fPaint = paint;
367
368    // if we only came in here for the imagefilter, mark us as done
369    if (!fLooper && !fFilter) {
370        fDone = true;
371    }
372
373    // call this after any possible paint modifiers
374    if (fPaint->nothingToDraw()) {
375        fPaint = NULL;
376        return false;
377    }
378    return true;
379}
380
381/*  Stack helper for managing a SkBounder. In the destructor, if we were
382    given a bounder, we call its commit() method, signifying that we are
383    done accumulating bounds for that draw.
384*/
385class SkAutoBounderCommit {
386public:
387    SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
388    ~SkAutoBounderCommit() {
389        if (NULL != fBounder) {
390            fBounder->commit();
391        }
392    }
393private:
394    SkBounder*  fBounder;
395};
396
397#include "SkColorPriv.h"
398
399class AutoValidator {
400public:
401    AutoValidator(SkDevice* device) : fDevice(device) {}
402    ~AutoValidator() {
403#ifdef SK_DEBUG
404        const SkBitmap& bm = fDevice->accessBitmap(false);
405        if (bm.config() == SkBitmap::kARGB_4444_Config) {
406            for (int y = 0; y < bm.height(); y++) {
407                const SkPMColor16* p = bm.getAddr16(0, y);
408                for (int x = 0; x < bm.width(); x++) {
409                    SkPMColor16 c = p[x];
410                    SkPMColor16Assert(c);
411                }
412            }
413        }
414#endif
415    }
416private:
417    SkDevice* fDevice;
418};
419
420////////// macros to place around the internal draw calls //////////////////
421
422#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
423/*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
424    this->predrawNotify();                                          \
425    AutoDrawLooper  looper(this, paint, true);                      \
426    while (looper.next(type)) {                                     \
427        SkAutoBounderCommit ac(fBounder);                           \
428        SkDrawIter          iter(this);
429
430#define LOOPER_BEGIN(paint, type)                                   \
431/*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
432    this->predrawNotify();                                          \
433    AutoDrawLooper  looper(this, paint);                            \
434    while (looper.next(type)) {                                     \
435        SkAutoBounderCommit ac(fBounder);                           \
436        SkDrawIter          iter(this);
437
438#define LOOPER_END    }
439
440////////////////////////////////////////////////////////////////////////////
441
442SkDevice* SkCanvas::init(SkDevice* device) {
443    fBounder = NULL;
444    fLocalBoundsCompareType.setEmpty();
445    fLocalBoundsCompareTypeDirty = true;
446    fAllowSoftClip = true;
447    fDeviceCMDirty = false;
448    fSaveLayerCount = 0;
449    fMetaData = NULL;
450
451    fMCRec = (MCRec*)fMCStack.push_back();
452    new (fMCRec) MCRec(NULL, 0);
453
454    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
455    fMCRec->fTopLayer = fMCRec->fLayer;
456    fMCRec->fNext = NULL;
457
458    fSurfaceBase = NULL;
459
460    return this->setDevice(device);
461}
462
463SkCanvas::SkCanvas()
464: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
465    inc_canvas();
466
467    this->init(NULL);
468}
469
470SkCanvas::SkCanvas(SkDevice* device)
471        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
472    inc_canvas();
473
474    this->init(device);
475}
476
477SkCanvas::SkCanvas(const SkBitmap& bitmap)
478        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
479    inc_canvas();
480
481    this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
482}
483
484SkCanvas::~SkCanvas() {
485    // free up the contents of our deque
486    this->restoreToCount(1);    // restore everything but the last
487    SkASSERT(0 == fSaveLayerCount);
488
489    this->internalRestore();    // restore the last, since we're going away
490
491    SkSafeUnref(fBounder);
492    SkDELETE(fMetaData);
493
494    dec_canvas();
495}
496
497SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
498    SkRefCnt_SafeAssign(fBounder, bounder);
499    return bounder;
500}
501
502SkDrawFilter* SkCanvas::getDrawFilter() const {
503    return fMCRec->fFilter;
504}
505
506SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
507    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
508    return filter;
509}
510
511SkMetaData& SkCanvas::getMetaData() {
512    // metadata users are rare, so we lazily allocate it. If that changes we
513    // can decide to just make it a field in the device (rather than a ptr)
514    if (NULL == fMetaData) {
515        fMetaData = new SkMetaData;
516    }
517    return *fMetaData;
518}
519
520///////////////////////////////////////////////////////////////////////////////
521
522void SkCanvas::flush() {
523    SkDevice* device = this->getDevice();
524    if (device) {
525        device->flush();
526    }
527}
528
529SkISize SkCanvas::getDeviceSize() const {
530    SkDevice* d = this->getDevice();
531    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
532}
533
534SkDevice* SkCanvas::getDevice() const {
535    // return root device
536    MCRec* rec = (MCRec*) fMCStack.front();
537    SkASSERT(rec && rec->fLayer);
538    return rec->fLayer->fDevice;
539}
540
541SkDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
542    if (updateMatrixClip) {
543        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
544    }
545    return fMCRec->fTopLayer->fDevice;
546}
547
548SkDevice* SkCanvas::setDevice(SkDevice* device) {
549    // return root device
550    SkDeque::F2BIter iter(fMCStack);
551    MCRec*           rec = (MCRec*)iter.next();
552    SkASSERT(rec && rec->fLayer);
553    SkDevice*       rootDevice = rec->fLayer->fDevice;
554
555    if (rootDevice == device) {
556        return device;
557    }
558
559    if (device) {
560        device->onAttachToCanvas(this);
561    }
562    if (rootDevice) {
563        rootDevice->onDetachFromCanvas();
564    }
565
566    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
567    rootDevice = device;
568
569    fDeviceCMDirty = true;
570
571    /*  Now we update our initial region to have the bounds of the new device,
572        and then intersect all of the clips in our stack with these bounds,
573        to ensure that we can't draw outside of the device's bounds (and trash
574                                                                     memory).
575
576    NOTE: this is only a partial-fix, since if the new device is larger than
577        the previous one, we don't know how to "enlarge" the clips in our stack,
578        so drawing may be artificially restricted. Without keeping a history of
579        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
580        reconstruct the correct clips, so this approximation will have to do.
581        The caller really needs to restore() back to the base if they want to
582        accurately take advantage of the new device bounds.
583    */
584
585    SkIRect bounds;
586    if (device) {
587        bounds.set(0, 0, device->width(), device->height());
588    } else {
589        bounds.setEmpty();
590    }
591    // now jam our 1st clip to be bounds, and intersect the rest with that
592    rec->fRasterClip->setRect(bounds);
593    while ((rec = (MCRec*)iter.next()) != NULL) {
594        (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
595    }
596
597    return device;
598}
599
600bool SkCanvas::readPixels(SkBitmap* bitmap,
601                          int x, int y,
602                          Config8888 config8888) {
603    SkDevice* device = this->getDevice();
604    if (!device) {
605        return false;
606    }
607    return device->readPixels(bitmap, x, y, config8888);
608}
609
610bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
611    SkDevice* device = this->getDevice();
612    if (!device) {
613        return false;
614    }
615
616    SkIRect bounds;
617    bounds.set(0, 0, device->width(), device->height());
618    if (!bounds.intersect(srcRect)) {
619        return false;
620    }
621
622    SkBitmap tmp;
623    tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
624                                               bounds.height());
625    if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
626        bitmap->swap(tmp);
627        return true;
628    } else {
629        return false;
630    }
631}
632
633void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y,
634                           Config8888 config8888) {
635    SkDevice* device = this->getDevice();
636    if (device) {
637        if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()),
638                                SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) {
639            device->accessBitmap(true);
640            device->writePixels(bitmap, x, y, config8888);
641        }
642    }
643}
644
645SkCanvas* SkCanvas::canvasForDrawIter() {
646    return this;
647}
648
649//////////////////////////////////////////////////////////////////////////////
650
651void SkCanvas::updateDeviceCMCache() {
652    if (fDeviceCMDirty) {
653        const SkMatrix& totalMatrix = this->getTotalMatrix();
654        const SkRasterClip& totalClip = *fMCRec->fRasterClip;
655        DeviceCM*       layer = fMCRec->fTopLayer;
656
657        if (NULL == layer->fNext) {   // only one layer
658            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
659        } else {
660            SkRasterClip clip(totalClip);
661            do {
662                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
663            } while ((layer = layer->fNext) != NULL);
664        }
665        fDeviceCMDirty = false;
666    }
667}
668
669///////////////////////////////////////////////////////////////////////////////
670
671int SkCanvas::internalSave(SaveFlags flags) {
672    int saveCount = this->getSaveCount(); // record this before the actual save
673
674    MCRec* newTop = (MCRec*)fMCStack.push_back();
675    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
676
677    newTop->fNext = fMCRec;
678    fMCRec = newTop;
679
680    fClipStack.save();
681    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
682
683    return saveCount;
684}
685
686int SkCanvas::save(SaveFlags flags) {
687    // call shared impl
688    return this->internalSave(flags);
689}
690
691#define C32MASK (1 << SkBitmap::kARGB_8888_Config)
692#define C16MASK (1 << SkBitmap::kRGB_565_Config)
693#define C8MASK  (1 << SkBitmap::kA8_Config)
694
695static SkBitmap::Config resolve_config(SkCanvas* canvas,
696                                       const SkIRect& bounds,
697                                       SkCanvas::SaveFlags flags,
698                                       bool* isOpaque) {
699    *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
700
701#if 0
702    // loop through and union all the configs we may draw into
703    uint32_t configMask = 0;
704    for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
705    {
706        SkDevice* device = canvas->getLayerDevice(i);
707        if (device->intersects(bounds))
708            configMask |= 1 << device->config();
709    }
710
711    // if the caller wants alpha or fullcolor, we can't return 565
712    if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
713                 SkCanvas::kHasAlphaLayer_SaveFlag))
714        configMask &= ~C16MASK;
715
716    switch (configMask) {
717    case C8MASK:    // if we only have A8, return that
718        return SkBitmap::kA8_Config;
719
720    case C16MASK:   // if we only have 565, return that
721        return SkBitmap::kRGB_565_Config;
722
723    default:
724        return SkBitmap::kARGB_8888_Config; // default answer
725    }
726#else
727    return SkBitmap::kARGB_8888_Config; // default answer
728#endif
729}
730
731static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
732    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
733}
734
735bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
736                               SkIRect* intersection) {
737    SkIRect clipBounds;
738    if (!this->getClipDeviceBounds(&clipBounds)) {
739        return false;
740    }
741    SkIRect ir;
742    if (NULL != bounds) {
743        SkRect r;
744
745        this->getTotalMatrix().mapRect(&r, *bounds);
746        r.roundOut(&ir);
747        // early exit if the layer's bounds are clipped out
748        if (!ir.intersect(clipBounds)) {
749            if (bounds_affects_clip(flags)) {
750                fMCRec->fRasterClip->setEmpty();
751            }
752            return false;
753        }
754    } else {    // no user bounds, so just use the clip
755        ir = clipBounds;
756    }
757
758    fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
759
760    // early exit if the clip is now empty
761    if (bounds_affects_clip(flags) &&
762        !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) {
763        return false;
764    }
765
766    if (intersection) {
767        *intersection = ir;
768    }
769    return true;
770}
771
772int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
773                        SaveFlags flags) {
774    return this->internalSaveLayer(bounds, paint, flags, false);
775}
776
777int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
778                                SaveFlags flags, bool justForImageFilter) {
779    // do this before we create the layer. We don't call the public save() since
780    // that would invoke a possibly overridden virtual
781    int count = this->internalSave(flags);
782
783    fDeviceCMDirty = true;
784
785    SkIRect ir;
786    if (!this->clipRectBounds(bounds, flags, &ir)) {
787        return count;
788    }
789
790    // Kill the imagefilter if our device doesn't allow it
791    SkLazyPaint lazyP;
792    if (paint && paint->getImageFilter()) {
793        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
794            if (justForImageFilter) {
795                // early exit if the layer was just for the imageFilter
796                return count;
797            }
798            SkPaint* p = lazyP.set(*paint);
799            p->setImageFilter(NULL);
800            paint = p;
801        }
802    }
803
804    bool isOpaque;
805    SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
806
807    SkDevice* device;
808    if (paint && paint->getImageFilter()) {
809        device = this->createCompatibleDevice(config, ir.width(), ir.height(),
810                                              isOpaque);
811    } else {
812        device = this->createLayerDevice(config, ir.width(), ir.height(),
813                                         isOpaque);
814    }
815    if (NULL == device) {
816        SkDebugf("Unable to create device for layer.");
817        return count;
818    }
819
820    device->setOrigin(ir.fLeft, ir.fTop);
821    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
822    device->unref();
823
824    layer->fNext = fMCRec->fTopLayer;
825    fMCRec->fLayer = layer;
826    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
827
828    fSaveLayerCount += 1;
829    return count;
830}
831
832int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
833                             SaveFlags flags) {
834    if (0xFF == alpha) {
835        return this->saveLayer(bounds, NULL, flags);
836    } else {
837        SkPaint tmpPaint;
838        tmpPaint.setAlpha(alpha);
839        return this->saveLayer(bounds, &tmpPaint, flags);
840    }
841}
842
843void SkCanvas::restore() {
844    // check for underflow
845    if (fMCStack.count() > 1) {
846        this->internalRestore();
847    }
848}
849
850void SkCanvas::internalRestore() {
851    SkASSERT(fMCStack.count() != 0);
852
853    fDeviceCMDirty = true;
854    fLocalBoundsCompareTypeDirty = true;
855
856    fClipStack.restore();
857    // reserve our layer (if any)
858    DeviceCM* layer = fMCRec->fLayer;   // may be null
859    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
860    fMCRec->fLayer = NULL;
861
862    // now do the normal restore()
863    fMCRec->~MCRec();       // balanced in save()
864    fMCStack.pop_back();
865    fMCRec = (MCRec*)fMCStack.back();
866
867    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
868        since if we're being recorded, we don't want to record this (the
869        recorder will have already recorded the restore).
870    */
871    if (NULL != layer) {
872        if (layer->fNext) {
873            const SkIPoint& origin = layer->fDevice->getOrigin();
874            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
875                                     layer->fPaint);
876            // reset this, since internalDrawDevice will have set it to true
877            fDeviceCMDirty = true;
878
879            SkASSERT(fSaveLayerCount > 0);
880            fSaveLayerCount -= 1;
881        }
882        SkDELETE(layer);
883    }
884
885    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
886}
887
888int SkCanvas::getSaveCount() const {
889    return fMCStack.count();
890}
891
892void SkCanvas::restoreToCount(int count) {
893    // sanity check
894    if (count < 1) {
895        count = 1;
896    }
897
898    int n = this->getSaveCount() - count;
899    for (int i = 0; i < n; ++i) {
900        this->restore();
901    }
902}
903
904bool SkCanvas::isDrawingToLayer() const {
905    return fSaveLayerCount > 0;
906}
907
908/////////////////////////////////////////////////////////////////////////////
909
910// can't draw it if its empty, or its too big for a fixed-point width or height
911static bool reject_bitmap(const SkBitmap& bitmap) {
912    return  bitmap.width() <= 0 || bitmap.height() <= 0
913#ifndef SK_ALLOW_OVER_32K_BITMAPS
914            || bitmap.width() > 32767 || bitmap.height() > 32767
915#endif
916            ;
917}
918
919void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
920                                const SkMatrix& matrix, const SkPaint* paint) {
921    if (reject_bitmap(bitmap)) {
922        return;
923    }
924
925    SkLazyPaint lazy;
926    if (NULL == paint) {
927        paint = lazy.init();
928    }
929    this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
930}
931
932void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y,
933                                  const SkPaint* paint) {
934    SkPaint tmp;
935    if (NULL == paint) {
936        tmp.setDither(true);
937        paint = &tmp;
938    }
939
940    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
941    while (iter.next()) {
942        SkDevice* dstDev = iter.fDevice;
943        paint = &looper.paint();
944        SkImageFilter* filter = paint->getImageFilter();
945        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
946        if (filter && !dstDev->canHandleImageFilter(filter)) {
947            SkDeviceImageFilterProxy proxy(dstDev);
948            SkBitmap dst;
949            const SkBitmap& src = srcDev->accessBitmap(false);
950            if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
951                SkPaint tmpUnfiltered(*paint);
952                tmpUnfiltered.setImageFilter(NULL);
953                dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered);
954            }
955        } else {
956            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
957        }
958    }
959    LOOPER_END
960}
961
962void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
963                          const SkPaint* paint) {
964    SkDEBUGCODE(bitmap.validate();)
965
966    if (reject_bitmap(bitmap)) {
967        return;
968    }
969
970    SkPaint tmp;
971    if (NULL == paint) {
972        paint = &tmp;
973    }
974
975    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
976
977    while (iter.next()) {
978        paint = &looper.paint();
979        SkImageFilter* filter = paint->getImageFilter();
980        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
981        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
982            SkDeviceImageFilterProxy proxy(iter.fDevice);
983            SkBitmap dst;
984            if (filter->filterImage(&proxy, bitmap, *iter.fMatrix,
985                                    &dst, &pos)) {
986                SkPaint tmpUnfiltered(*paint);
987                tmpUnfiltered.setImageFilter(NULL);
988                iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(),
989                                         tmpUnfiltered);
990            }
991        } else {
992            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
993        }
994    }
995    LOOPER_END
996}
997
998/////////////////////////////////////////////////////////////////////////////
999
1000bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
1001    fDeviceCMDirty = true;
1002    fLocalBoundsCompareTypeDirty = true;
1003    return fMCRec->fMatrix->preTranslate(dx, dy);
1004}
1005
1006bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
1007    fDeviceCMDirty = true;
1008    fLocalBoundsCompareTypeDirty = true;
1009    return fMCRec->fMatrix->preScale(sx, sy);
1010}
1011
1012bool SkCanvas::rotate(SkScalar degrees) {
1013    fDeviceCMDirty = true;
1014    fLocalBoundsCompareTypeDirty = true;
1015    return fMCRec->fMatrix->preRotate(degrees);
1016}
1017
1018bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
1019    fDeviceCMDirty = true;
1020    fLocalBoundsCompareTypeDirty = true;
1021    return fMCRec->fMatrix->preSkew(sx, sy);
1022}
1023
1024bool SkCanvas::concat(const SkMatrix& matrix) {
1025    fDeviceCMDirty = true;
1026    fLocalBoundsCompareTypeDirty = true;
1027    return fMCRec->fMatrix->preConcat(matrix);
1028}
1029
1030void SkCanvas::setMatrix(const SkMatrix& matrix) {
1031    fDeviceCMDirty = true;
1032    fLocalBoundsCompareTypeDirty = true;
1033    *fMCRec->fMatrix = matrix;
1034}
1035
1036// this is not virtual, so it must call a virtual method so that subclasses
1037// will see its action
1038void SkCanvas::resetMatrix() {
1039    SkMatrix matrix;
1040
1041    matrix.reset();
1042    this->setMatrix(matrix);
1043}
1044
1045//////////////////////////////////////////////////////////////////////////////
1046
1047bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1048#ifdef SK_ENABLE_CLIP_QUICKREJECT
1049    if (SkRegion::kIntersect_Op == op) {
1050        if (fMCRec->fRasterClip->isEmpty()) {
1051            return false;
1052        }
1053
1054        if (this->quickReject(rect)) {
1055            fDeviceCMDirty = true;
1056            fLocalBoundsCompareTypeDirty = true;
1057
1058            fClipStack.clipEmpty();
1059            return fMCRec->fRasterClip->setEmpty();
1060        }
1061    }
1062#endif
1063
1064    AutoValidateClip avc(this);
1065
1066    fDeviceCMDirty = true;
1067    fLocalBoundsCompareTypeDirty = true;
1068    doAA &= fAllowSoftClip;
1069
1070    if (fMCRec->fMatrix->rectStaysRect()) {
1071        // for these simpler matrices, we can stay a rect ever after applying
1072        // the matrix. This means we don't have to a) make a path, and b) tell
1073        // the region code to scan-convert the path, only to discover that it
1074        // is really just a rect.
1075        SkRect      r;
1076
1077        fMCRec->fMatrix->mapRect(&r, rect);
1078        fClipStack.clipDevRect(r, op, doAA);
1079        return fMCRec->fRasterClip->op(r, op, doAA);
1080    } else {
1081        // since we're rotate or some such thing, we convert the rect to a path
1082        // and clip against that, since it can handle any matrix. However, to
1083        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1084        // we explicitly call "our" version of clipPath.
1085        SkPath  path;
1086
1087        path.addRect(rect);
1088        return this->SkCanvas::clipPath(path, op, doAA);
1089    }
1090}
1091
1092static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
1093                           const SkPath& devPath, SkRegion::Op op, bool doAA) {
1094    // base is used to limit the size (and therefore memory allocation) of the
1095    // region that results from scan converting devPath.
1096    SkRegion base;
1097
1098    if (SkRegion::kIntersect_Op == op) {
1099        // since we are intersect, we can do better (tighter) with currRgn's
1100        // bounds, than just using the device. However, if currRgn is complex,
1101        // our region blitter may hork, so we do that case in two steps.
1102        if (currClip->isRect()) {
1103            return currClip->setPath(devPath, *currClip, doAA);
1104        } else {
1105            base.setRect(currClip->getBounds());
1106            SkRasterClip clip;
1107            clip.setPath(devPath, base, doAA);
1108            return currClip->op(clip, op);
1109        }
1110    } else {
1111        const SkDevice* device = canvas->getDevice();
1112        if (!device) {
1113            return currClip->setEmpty();
1114        }
1115
1116        base.setRect(0, 0, device->width(), device->height());
1117
1118        if (SkRegion::kReplace_Op == op) {
1119            return currClip->setPath(devPath, base, doAA);
1120        } else {
1121            SkRasterClip clip;
1122            clip.setPath(devPath, base, doAA);
1123            return currClip->op(clip, op);
1124        }
1125    }
1126}
1127
1128bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1129#ifdef SK_ENABLE_CLIP_QUICKREJECT
1130    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1131        if (fMCRec->fRasterClip->isEmpty()) {
1132            return false;
1133        }
1134
1135        if (this->quickReject(path.getBounds())) {
1136            fDeviceCMDirty = true;
1137            fLocalBoundsCompareTypeDirty = true;
1138
1139            fClipStack.clipEmpty();
1140            return fMCRec->fRasterClip->setEmpty();
1141        }
1142    }
1143#endif
1144
1145    AutoValidateClip avc(this);
1146
1147    fDeviceCMDirty = true;
1148    fLocalBoundsCompareTypeDirty = true;
1149    doAA &= fAllowSoftClip;
1150
1151    SkPath devPath;
1152    path.transform(*fMCRec->fMatrix, &devPath);
1153
1154    // Check if the transfomation, or the original path itself
1155    // made us empty. Note this can also happen if we contained NaN
1156    // values. computing the bounds detects this, and will set our
1157    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1158    if (devPath.getBounds().isEmpty()) {
1159        // resetting the path will remove any NaN or other wanky values
1160        // that might upset our scan converter.
1161        devPath.reset();
1162    }
1163
1164    // if we called path.swap() we could avoid a deep copy of this path
1165    fClipStack.clipDevPath(devPath, op, doAA);
1166
1167    return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
1168}
1169
1170bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1171    AutoValidateClip avc(this);
1172
1173    fDeviceCMDirty = true;
1174    fLocalBoundsCompareTypeDirty = true;
1175
1176    // todo: signal fClipStack that we have a region, and therefore (I guess)
1177    // we have to ignore it, and use the region directly?
1178    fClipStack.clipDevRect(rgn.getBounds(), op);
1179
1180    return fMCRec->fRasterClip->op(rgn, op);
1181}
1182
1183#ifdef SK_DEBUG
1184void SkCanvas::validateClip() const {
1185    // construct clipRgn from the clipstack
1186    const SkDevice* device = this->getDevice();
1187    if (!device) {
1188        SkASSERT(this->getTotalClip().isEmpty());
1189        return;
1190    }
1191
1192    SkIRect ir;
1193    ir.set(0, 0, device->width(), device->height());
1194    SkRasterClip tmpClip(ir);
1195
1196    SkClipStack::B2TIter                iter(fClipStack);
1197    const SkClipStack::B2TIter::Clip*   clip;
1198    while ((clip = iter.next()) != NULL) {
1199        if (clip->fPath) {
1200            clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA);
1201        } else if (clip->fRect) {
1202            clip->fRect->round(&ir);
1203            tmpClip.op(ir, clip->fOp);
1204        } else {
1205            tmpClip.setEmpty();
1206        }
1207    }
1208
1209#if 0   // enable this locally for testing
1210    // now compare against the current rgn
1211    const SkRegion& rgn = this->getTotalClip();
1212    SkASSERT(rgn == tmpClip);
1213#endif
1214}
1215#endif
1216
1217void SkCanvas::replayClips(ClipVisitor* visitor) const {
1218    SkClipStack::B2TIter                iter(fClipStack);
1219    const SkClipStack::B2TIter::Clip*   clip;
1220
1221    SkRect empty = { 0, 0, 0, 0 };
1222    while ((clip = iter.next()) != NULL) {
1223        if (clip->fPath) {
1224            visitor->clipPath(*clip->fPath, clip->fOp, clip->fDoAA);
1225        } else if (clip->fRect) {
1226            visitor->clipRect(*clip->fRect, clip->fOp, clip->fDoAA);
1227        } else {
1228            visitor->clipRect(empty, SkRegion::kIntersect_Op, false);
1229        }
1230    }
1231}
1232
1233///////////////////////////////////////////////////////////////////////////////
1234
1235void SkCanvas::computeLocalClipBoundsCompareType() const {
1236    SkRect r;
1237
1238    if (!this->getClipBounds(&r)) {
1239        fLocalBoundsCompareType.setEmpty();
1240    } else {
1241        fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft),
1242                                    SkScalarToCompareType(r.fTop),
1243                                    SkScalarToCompareType(r.fRight),
1244                                    SkScalarToCompareType(r.fBottom));
1245    }
1246}
1247
1248bool SkCanvas::quickReject(const SkRect& rect) const {
1249
1250    if (!rect.isFinite())
1251        return true;
1252
1253    if (fMCRec->fRasterClip->isEmpty()) {
1254        return true;
1255    }
1256
1257    if (fMCRec->fMatrix->hasPerspective()) {
1258        SkRect dst;
1259        fMCRec->fMatrix->mapRect(&dst, rect);
1260        SkIRect idst;
1261        dst.roundOut(&idst);
1262        return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1263    } else {
1264        const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
1265
1266        // for speed, do the most likely reject compares first
1267        SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
1268        SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
1269        if (userT >= clipR.fBottom || userB <= clipR.fTop) {
1270            return true;
1271        }
1272        SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
1273        SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
1274        if (userL >= clipR.fRight || userR <= clipR.fLeft) {
1275            return true;
1276        }
1277        return false;
1278    }
1279}
1280
1281bool SkCanvas::quickReject(const SkPath& path) const {
1282    return path.isEmpty() || this->quickReject(path.getBounds());
1283}
1284
1285static inline int pinIntForScalar(int x) {
1286#ifdef SK_SCALAR_IS_FIXED
1287    if (x < SK_MinS16) {
1288        x = SK_MinS16;
1289    } else if (x > SK_MaxS16) {
1290        x = SK_MaxS16;
1291    }
1292#endif
1293    return x;
1294}
1295
1296bool SkCanvas::getClipBounds(SkRect* bounds) const {
1297    SkIRect ibounds;
1298    if (!getClipDeviceBounds(&ibounds)) {
1299        return false;
1300    }
1301
1302    SkMatrix inverse;
1303    // if we can't invert the CTM, we can't return local clip bounds
1304    if (!fMCRec->fMatrix->invert(&inverse)) {
1305        if (bounds) {
1306            bounds->setEmpty();
1307        }
1308        return false;
1309    }
1310
1311    if (NULL != bounds) {
1312        SkRect r;
1313        // adjust it outwards in case we are antialiasing
1314        const int inset = 1;
1315
1316        // SkRect::iset() will correctly assert if we pass a value out of range
1317        // (when SkScalar==fixed), so we pin to legal values. This does not
1318        // really returnt the correct answer, but its the best we can do given
1319        // that we've promised to return SkRect (even though we support devices
1320        // that can be larger than 32K in width or height).
1321        r.iset(pinIntForScalar(ibounds.fLeft - inset),
1322               pinIntForScalar(ibounds.fTop - inset),
1323               pinIntForScalar(ibounds.fRight + inset),
1324               pinIntForScalar(ibounds.fBottom + inset));
1325        inverse.mapRect(bounds, r);
1326    }
1327    return true;
1328}
1329
1330bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1331    const SkRasterClip& clip = *fMCRec->fRasterClip;
1332    if (clip.isEmpty()) {
1333        if (bounds) {
1334            bounds->setEmpty();
1335        }
1336        return false;
1337    }
1338
1339    if (NULL != bounds) {
1340        *bounds = clip.getBounds();
1341    }
1342    return true;
1343}
1344
1345const SkMatrix& SkCanvas::getTotalMatrix() const {
1346    return *fMCRec->fMatrix;
1347}
1348
1349SkCanvas::ClipType SkCanvas::getClipType() const {
1350    if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
1351    if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
1352    return kComplex_ClipType;
1353}
1354
1355const SkRegion& SkCanvas::getTotalClip() const {
1356    return fMCRec->fRasterClip->forceGetBW();
1357}
1358
1359SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
1360                                      int width, int height,
1361                                      bool isOpaque) {
1362    SkDevice* device = this->getTopDevice();
1363    if (device) {
1364        return device->createCompatibleDeviceForSaveLayer(config, width, height,
1365                                                          isOpaque);
1366    } else {
1367        return NULL;
1368    }
1369}
1370
1371SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
1372                                           int width, int height,
1373                                           bool isOpaque) {
1374    SkDevice* device = this->getDevice();
1375    if (device) {
1376        return device->createCompatibleDevice(config, width, height, isOpaque);
1377    } else {
1378        return NULL;
1379    }
1380}
1381
1382
1383//////////////////////////////////////////////////////////////////////////////
1384//  These are the virtual drawing methods
1385//////////////////////////////////////////////////////////////////////////////
1386
1387void SkCanvas::clear(SkColor color) {
1388    SkDrawIter  iter(this);
1389
1390    while (iter.next()) {
1391        iter.fDevice->clear(color);
1392    }
1393}
1394
1395void SkCanvas::drawPaint(const SkPaint& paint) {
1396    this->internalDrawPaint(paint);
1397}
1398
1399void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1400    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
1401
1402    while (iter.next()) {
1403        iter.fDevice->drawPaint(iter, looper.paint());
1404    }
1405
1406    LOOPER_END
1407}
1408
1409void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1410                          const SkPaint& paint) {
1411    if ((long)count <= 0) {
1412        return;
1413    }
1414
1415    if (paint.canComputeFastBounds()) {
1416        SkRect r;
1417        // special-case 2 points (common for drawing a single line)
1418        if (2 == count) {
1419            r.set(pts[0], pts[1]);
1420        } else {
1421            r.set(pts, count);
1422        }
1423        SkRect storage;
1424        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
1425            return;
1426        }
1427    }
1428
1429    SkASSERT(pts != NULL);
1430
1431    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1432
1433    while (iter.next()) {
1434        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1435    }
1436
1437    LOOPER_END
1438}
1439
1440void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1441    if (paint.canComputeFastBounds()) {
1442        SkRect storage;
1443        if (this->quickReject(paint.computeFastBounds(r, &storage))) {
1444            return;
1445        }
1446    }
1447
1448    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
1449
1450    while (iter.next()) {
1451        iter.fDevice->drawRect(iter, r, looper.paint());
1452    }
1453
1454    LOOPER_END
1455}
1456
1457void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1458    if (!path.isFinite()) {
1459        return;
1460    }
1461
1462    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1463        SkRect storage;
1464        const SkRect& bounds = path.getBounds();
1465        if (this->quickReject(paint.computeFastBounds(bounds, &storage))) {
1466            return;
1467        }
1468    }
1469    if (path.isEmpty()) {
1470        if (path.isInverseFillType()) {
1471            this->internalDrawPaint(paint);
1472        }
1473        return;
1474    }
1475
1476    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1477
1478    while (iter.next()) {
1479        iter.fDevice->drawPath(iter, path, looper.paint());
1480    }
1481
1482    LOOPER_END
1483}
1484
1485void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1486                          const SkPaint* paint) {
1487    SkDEBUGCODE(bitmap.validate();)
1488
1489    if (NULL == paint || paint->canComputeFastBounds()) {
1490        SkRect bounds = {
1491            x, y,
1492            x + SkIntToScalar(bitmap.width()),
1493            y + SkIntToScalar(bitmap.height())
1494        };
1495        if (paint) {
1496            (void)paint->computeFastBounds(bounds, &bounds);
1497        }
1498        if (this->quickReject(bounds)) {
1499            return;
1500        }
1501    }
1502
1503    SkMatrix matrix;
1504    matrix.setTranslate(x, y);
1505    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1506}
1507
1508// this one is non-virtual, so it can be called safely by other canvas apis
1509void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1510                                      const SkRect& dst, const SkPaint* paint) {
1511    if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1512        return;
1513    }
1514
1515    if (NULL == paint || paint->canComputeFastBounds()) {
1516        SkRect storage;
1517        const SkRect* bounds = &dst;
1518        if (paint) {
1519            bounds = &paint->computeFastBounds(dst, &storage);
1520        }
1521        if (this->quickReject(*bounds)) {
1522            return;
1523        }
1524    }
1525
1526    SkLazyPaint lazy;
1527    if (NULL == paint) {
1528        paint = lazy.init();
1529    }
1530
1531    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1532
1533    while (iter.next()) {
1534        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint());
1535    }
1536
1537    LOOPER_END
1538}
1539
1540void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1541                                    const SkRect& dst, const SkPaint* paint) {
1542    SkDEBUGCODE(bitmap.validate();)
1543    this->internalDrawBitmapRect(bitmap, src, dst, paint);
1544}
1545
1546void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1547                                const SkPaint* paint) {
1548    SkDEBUGCODE(bitmap.validate();)
1549    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1550}
1551
1552void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
1553                                const SkMatrix& matrix, const SkPaint& paint) {
1554    SkDEBUGCODE(bitmap.validate();)
1555
1556    LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1557
1558    while (iter.next()) {
1559        iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
1560    }
1561
1562    LOOPER_END
1563}
1564
1565void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1566                                      const SkIRect& center, const SkRect& dst,
1567                                      const SkPaint* paint) {
1568    if (NULL == paint || paint->canComputeFastBounds()) {
1569        SkRect storage;
1570        const SkRect* bounds = &dst;
1571        if (paint) {
1572            bounds = &paint->computeFastBounds(dst, &storage);
1573        }
1574        if (this->quickReject(*bounds)) {
1575            return;
1576        }
1577    }
1578
1579    const int32_t w = bitmap.width();
1580    const int32_t h = bitmap.height();
1581
1582    SkIRect c = center;
1583    // pin center to the bounds of the bitmap
1584    c.fLeft = SkMax32(0, center.fLeft);
1585    c.fTop = SkMax32(0, center.fTop);
1586    c.fRight = SkPin32(center.fRight, c.fLeft, w);
1587    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1588
1589    const SkScalar srcX[4] = {
1590        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), w
1591    };
1592    const SkScalar srcY[4] = {
1593        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), h
1594    };
1595    SkScalar dstX[4] = {
1596        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1597        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1598    };
1599    SkScalar dstY[4] = {
1600        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1601        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1602    };
1603
1604    if (dstX[1] > dstX[2]) {
1605        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1606        dstX[2] = dstX[1];
1607    }
1608
1609    if (dstY[1] > dstY[2]) {
1610        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1611        dstY[2] = dstY[1];
1612    }
1613
1614    for (int y = 0; y < 3; y++) {
1615        SkRect s, d;
1616
1617        s.fTop = srcY[y];
1618        s.fBottom = srcY[y+1];
1619        d.fTop = dstY[y];
1620        d.fBottom = dstY[y+1];
1621        for (int x = 0; x < 3; x++) {
1622            s.fLeft = srcX[x];
1623            s.fRight = srcX[x+1];
1624            d.fLeft = dstX[x];
1625            d.fRight = dstX[x+1];
1626            this->internalDrawBitmapRect(bitmap, &s, d, paint);
1627        }
1628    }
1629}
1630
1631void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1632                              const SkRect& dst, const SkPaint* paint) {
1633    SkDEBUGCODE(bitmap.validate();)
1634
1635    // Need a device entry-point, so gpu can use a mesh
1636    this->internalDrawBitmapNine(bitmap, center, dst, paint);
1637}
1638
1639class SkDeviceFilteredPaint {
1640public:
1641    SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
1642        SkDevice::TextFlags flags;
1643        if (device->filterTextFlags(paint, &flags)) {
1644            SkPaint* newPaint = fLazy.set(paint);
1645            newPaint->setFlags(flags.fFlags);
1646            newPaint->setHinting(flags.fHinting);
1647            fPaint = newPaint;
1648        } else {
1649            fPaint = &paint;
1650        }
1651    }
1652
1653    const SkPaint& paint() const { return *fPaint; }
1654
1655private:
1656    const SkPaint*  fPaint;
1657    SkLazyPaint     fLazy;
1658};
1659
1660void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
1661                        const SkRect& r, SkScalar textSize) {
1662    if (paint.getStyle() == SkPaint::kFill_Style) {
1663        draw.fDevice->drawRect(draw, r, paint);
1664    } else {
1665        SkPaint p(paint);
1666        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1667        draw.fDevice->drawRect(draw, r, p);
1668    }
1669}
1670
1671void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1672                                   const char text[], size_t byteLength,
1673                                   SkScalar x, SkScalar y) {
1674    SkASSERT(byteLength == 0 || text != NULL);
1675
1676    // nothing to draw
1677    if (text == NULL || byteLength == 0 ||
1678        draw.fClip->isEmpty() ||
1679        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1680        return;
1681    }
1682
1683    SkScalar    width = 0;
1684    SkPoint     start;
1685
1686    start.set(0, 0);    // to avoid warning
1687    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1688                            SkPaint::kStrikeThruText_Flag)) {
1689        width = paint.measureText(text, byteLength);
1690
1691        SkScalar offsetX = 0;
1692        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1693            offsetX = SkScalarHalf(width);
1694        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1695            offsetX = width;
1696        }
1697        start.set(x - offsetX, y);
1698    }
1699
1700    if (0 == width) {
1701        return;
1702    }
1703
1704    uint32_t flags = paint.getFlags();
1705
1706    if (flags & (SkPaint::kUnderlineText_Flag |
1707                 SkPaint::kStrikeThruText_Flag)) {
1708        SkScalar textSize = paint.getTextSize();
1709        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1710        SkRect   r;
1711
1712        r.fLeft = start.fX;
1713        r.fRight = start.fX + width;
1714
1715        if (flags & SkPaint::kUnderlineText_Flag) {
1716            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1717                                             start.fY);
1718            r.fTop = offset;
1719            r.fBottom = offset + height;
1720            DrawRect(draw, paint, r, textSize);
1721        }
1722        if (flags & SkPaint::kStrikeThruText_Flag) {
1723            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1724                                             start.fY);
1725            r.fTop = offset;
1726            r.fBottom = offset + height;
1727            DrawRect(draw, paint, r, textSize);
1728        }
1729    }
1730}
1731
1732void SkCanvas::drawText(const void* text, size_t byteLength,
1733                        SkScalar x, SkScalar y, const SkPaint& paint) {
1734    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1735
1736    while (iter.next()) {
1737        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1738        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
1739        DrawTextDecorations(iter, dfp.paint(),
1740                            static_cast<const char*>(text), byteLength, x, y);
1741    }
1742
1743    LOOPER_END
1744}
1745
1746void SkCanvas::drawPosText(const void* text, size_t byteLength,
1747                           const SkPoint pos[], const SkPaint& paint) {
1748    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1749
1750    while (iter.next()) {
1751        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1752        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1753                                  dfp.paint());
1754    }
1755
1756    LOOPER_END
1757}
1758
1759void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1760                            const SkScalar xpos[], SkScalar constY,
1761                            const SkPaint& paint) {
1762    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1763
1764    while (iter.next()) {
1765        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1766        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1767                                  dfp.paint());
1768    }
1769
1770    LOOPER_END
1771}
1772
1773void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1774                              const SkPath& path, const SkMatrix* matrix,
1775                              const SkPaint& paint) {
1776    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1777
1778    while (iter.next()) {
1779        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1780                                     matrix, looper.paint());
1781    }
1782
1783    LOOPER_END
1784}
1785
1786#ifdef SK_BUILD_FOR_ANDROID
1787void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
1788                                 const SkPoint pos[], const SkPaint& paint,
1789                                 const SkPath& path, const SkMatrix* matrix) {
1790    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1791
1792    while (iter.next()) {
1793        iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
1794                                        looper.paint(), path, matrix);
1795    }
1796
1797    LOOPER_END
1798}
1799#endif
1800
1801void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1802                            const SkPoint verts[], const SkPoint texs[],
1803                            const SkColor colors[], SkXfermode* xmode,
1804                            const uint16_t indices[], int indexCount,
1805                            const SkPaint& paint) {
1806    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1807
1808    while (iter.next()) {
1809        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1810                                   colors, xmode, indices, indexCount,
1811                                   looper.paint());
1812    }
1813
1814    LOOPER_END
1815}
1816
1817void SkCanvas::drawData(const void* data, size_t length) {
1818    // do nothing. Subclasses may do something with the data
1819}
1820
1821//////////////////////////////////////////////////////////////////////////////
1822// These methods are NOT virtual, and therefore must call back into virtual
1823// methods, rather than actually drawing themselves.
1824//////////////////////////////////////////////////////////////////////////////
1825
1826void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1827                        SkXfermode::Mode mode) {
1828    SkPaint paint;
1829
1830    paint.setARGB(a, r, g, b);
1831    if (SkXfermode::kSrcOver_Mode != mode) {
1832        paint.setXfermodeMode(mode);
1833    }
1834    this->drawPaint(paint);
1835}
1836
1837void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
1838    SkPaint paint;
1839
1840    paint.setColor(c);
1841    if (SkXfermode::kSrcOver_Mode != mode) {
1842        paint.setXfermodeMode(mode);
1843    }
1844    this->drawPaint(paint);
1845}
1846
1847void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
1848    SkPoint pt;
1849
1850    pt.set(x, y);
1851    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1852}
1853
1854void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
1855    SkPoint pt;
1856    SkPaint paint;
1857
1858    pt.set(x, y);
1859    paint.setColor(color);
1860    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1861}
1862
1863void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
1864                        const SkPaint& paint) {
1865    SkPoint pts[2];
1866
1867    pts[0].set(x0, y0);
1868    pts[1].set(x1, y1);
1869    this->drawPoints(kLines_PointMode, 2, pts, paint);
1870}
1871
1872void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
1873                              SkScalar right, SkScalar bottom,
1874                              const SkPaint& paint) {
1875    SkRect  r;
1876
1877    r.set(left, top, right, bottom);
1878    this->drawRect(r, paint);
1879}
1880
1881void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
1882                          const SkPaint& paint) {
1883    if (radius < 0) {
1884        radius = 0;
1885    }
1886
1887    SkRect  r;
1888    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
1889
1890    if (paint.canComputeFastBounds()) {
1891        SkRect storage;
1892        if (this->quickReject(paint.computeFastBounds(r, &storage))) {
1893            return;
1894        }
1895    }
1896
1897    SkPath  path;
1898    path.addOval(r);
1899    this->drawPath(path, paint);
1900}
1901
1902void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
1903                             const SkPaint& paint) {
1904    if (rx > 0 && ry > 0) {
1905        if (paint.canComputeFastBounds()) {
1906            SkRect storage;
1907            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
1908                return;
1909            }
1910        }
1911
1912        SkPath  path;
1913        path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
1914        this->drawPath(path, paint);
1915    } else {
1916        this->drawRect(r, paint);
1917    }
1918}
1919
1920void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1921    if (paint.canComputeFastBounds()) {
1922        SkRect storage;
1923        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
1924            return;
1925        }
1926    }
1927
1928    SkPath  path;
1929    path.addOval(oval);
1930    this->drawPath(path, paint);
1931}
1932
1933void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
1934                       SkScalar sweepAngle, bool useCenter,
1935                       const SkPaint& paint) {
1936    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
1937        this->drawOval(oval, paint);
1938    } else {
1939        SkPath  path;
1940        if (useCenter) {
1941            path.moveTo(oval.centerX(), oval.centerY());
1942        }
1943        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
1944        if (useCenter) {
1945            path.close();
1946        }
1947        this->drawPath(path, paint);
1948    }
1949}
1950
1951void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
1952                                const SkPath& path, SkScalar hOffset,
1953                                SkScalar vOffset, const SkPaint& paint) {
1954    SkMatrix    matrix;
1955
1956    matrix.setTranslate(hOffset, vOffset);
1957    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
1958}
1959
1960///////////////////////////////////////////////////////////////////////////////
1961
1962void SkCanvas::drawPicture(SkPicture& picture) {
1963    picture.draw(this);
1964}
1965
1966///////////////////////////////////////////////////////////////////////////////
1967///////////////////////////////////////////////////////////////////////////////
1968
1969SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
1970    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
1971
1972    SkASSERT(canvas);
1973
1974    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
1975    fDone = !fImpl->next();
1976}
1977
1978SkCanvas::LayerIter::~LayerIter() {
1979    fImpl->~SkDrawIter();
1980}
1981
1982void SkCanvas::LayerIter::next() {
1983    fDone = !fImpl->next();
1984}
1985
1986SkDevice* SkCanvas::LayerIter::device() const {
1987    return fImpl->getDevice();
1988}
1989
1990const SkMatrix& SkCanvas::LayerIter::matrix() const {
1991    return fImpl->getMatrix();
1992}
1993
1994const SkPaint& SkCanvas::LayerIter::paint() const {
1995    const SkPaint* paint = fImpl->getPaint();
1996    if (NULL == paint) {
1997        paint = &fDefaultPaint;
1998    }
1999    return *paint;
2000}
2001
2002const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2003int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2004int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2005
2006///////////////////////////////////////////////////////////////////////////////
2007
2008SkCanvas::ClipVisitor::~ClipVisitor() { }
2009
2010
2011