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