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