SkCanvas.cpp revision f76bacff7f66724072c67edb185abf9e3add11a0
1/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "SkCanvas.h"
18#include "SkBounder.h"
19#include "SkDevice.h"
20#include "SkDraw.h"
21#include "SkDrawFilter.h"
22#include "SkDrawLooper.h"
23#include "SkPicture.h"
24#include "SkScalarCompare.h"
25#include "SkShape.h"
26#include "SkTemplates.h"
27#include "SkUtils.h"
28#include <new>
29
30//#define SK_TRACE_SAVERESTORE
31
32#ifdef SK_TRACE_SAVERESTORE
33    static int gLayerCounter;
34    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
35    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
36
37    static int gRecCounter;
38    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
39    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
40
41    static int gCanvasCounter;
42    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
43    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
44#else
45    #define inc_layer()
46    #define dec_layer()
47    #define inc_rec()
48    #define dec_rec()
49    #define inc_canvas()
50    #define dec_canvas()
51#endif
52
53///////////////////////////////////////////////////////////////////////////////
54// Helpers for computing fast bounds for quickReject tests
55
56static SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) {
57    return paint != NULL && paint->isAntiAlias() ?
58            SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType;
59}
60
61///////////////////////////////////////////////////////////////////////////////
62
63/*  This is the record we keep for each SkDevice that the user installs.
64    The clip/matrix/proc are fields that reflect the top of the save/restore
65    stack. Whenever the canvas changes, it marks a dirty flag, and then before
66    these are used (assuming we're not on a layer) we rebuild these cache
67    values: they reflect the top of the save stack, but translated and clipped
68    by the device's XY offset and bitmap-bounds.
69*/
70struct DeviceCM {
71    DeviceCM*           fNext;
72    SkDevice*           fDevice;
73    SkRegion            fClip;
74    const SkMatrix*     fMatrix;
75	SkPaint*			fPaint;	// may be null (in the future)
76    int16_t             fX, fY; // relative to base matrix/clip
77
78	DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
79            : fNext(NULL) {
80        if (NULL != device) {
81            device->ref();
82            device->lockPixels();
83        }
84        fDevice = device;
85        fX = SkToS16(x);
86        fY = SkToS16(y);
87        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
88	}
89
90	~DeviceCM() {
91        if (NULL != fDevice) {
92            fDevice->unlockPixels();
93            fDevice->unref();
94        }
95		SkDELETE(fPaint);
96	}
97
98    void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip,
99                  SkRegion* updateClip) {
100        int x = fX;
101        int y = fY;
102        int width = fDevice->width();
103        int height = fDevice->height();
104
105        if ((x | y) == 0) {
106            fMatrix = &totalMatrix;
107            fClip = totalClip;
108        } else {
109            fMatrixStorage = totalMatrix;
110            fMatrixStorage.postTranslate(SkIntToScalar(-x),
111                                         SkIntToScalar(-y));
112            fMatrix = &fMatrixStorage;
113
114            totalClip.translate(-x, -y, &fClip);
115        }
116
117        fClip.op(0, 0, width, height, SkRegion::kIntersect_Op);
118
119        // intersect clip, but don't translate it (yet)
120
121        if (updateClip) {
122            updateClip->op(x, y, x + width, y + height,
123                           SkRegion::kDifference_Op);
124        }
125
126        fDevice->setMatrixClip(*fMatrix, fClip);
127
128#ifdef SK_DEBUG
129        if (!fClip.isEmpty()) {
130            SkIRect deviceR;
131            deviceR.set(0, 0, width, height);
132            SkASSERT(deviceR.contains(fClip.getBounds()));
133        }
134#endif
135    }
136
137    void translateClip() {
138        if (fX | fY) {
139            fClip.translate(fX, fY);
140        }
141    }
142
143private:
144    SkMatrix    fMatrixStorage;
145};
146
147/*  This is the record we keep for each save/restore level in the stack.
148    Since a level optionally copies the matrix and/or stack, we have pointers
149    for these fields. If the value is copied for this level, the copy is
150    stored in the ...Storage field, and the pointer points to that. If the
151    value is not copied for this level, we ignore ...Storage, and just point
152    at the corresponding value in the previous level in the stack.
153*/
154class SkCanvas::MCRec {
155public:
156    MCRec*          fNext;
157    SkMatrix*       fMatrix;    // points to either fMatrixStorage or prev MCRec
158    SkRegion*       fRegion;    // points to either fRegionStorage or prev MCRec
159    SkDrawFilter*   fFilter;    // the current filter (or null)
160
161    DeviceCM*   fLayer;
162    /*  If there are any layers in the stack, this points to the top-most
163        one that is at or below this level in the stack (so we know what
164        bitmap/device to draw into from this level. This value is NOT
165        reference counted, since the real owner is either our fLayer field,
166        or a previous one in a lower level.)
167    */
168    DeviceCM*	fTopLayer;
169
170    MCRec(const MCRec* prev, int flags) {
171        if (NULL != prev) {
172            if (flags & SkCanvas::kMatrix_SaveFlag) {
173                fMatrixStorage = *prev->fMatrix;
174                fMatrix = &fMatrixStorage;
175            } else {
176                fMatrix = prev->fMatrix;
177            }
178
179            if (flags & SkCanvas::kClip_SaveFlag) {
180                fRegionStorage = *prev->fRegion;
181                fRegion = &fRegionStorage;
182            } else {
183                fRegion = prev->fRegion;
184            }
185
186            fFilter = prev->fFilter;
187            fFilter->safeRef();
188
189            fTopLayer = prev->fTopLayer;
190        } else {   // no prev
191            fMatrixStorage.reset();
192
193            fMatrix     = &fMatrixStorage;
194            fRegion     = &fRegionStorage;
195            fFilter     = NULL;
196            fTopLayer   = NULL;
197        }
198        fLayer = NULL;
199
200        // don't bother initializing fNext
201        inc_rec();
202    }
203    ~MCRec() {
204        fFilter->safeUnref();
205        SkDELETE(fLayer);
206        dec_rec();
207    }
208
209private:
210    SkMatrix    fMatrixStorage;
211    SkRegion    fRegionStorage;
212};
213
214class SkDrawIter : public SkDraw {
215public:
216    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
217        fCanvas = canvas;
218        canvas->updateDeviceCMCache();
219
220        fBounder = canvas->getBounder();
221        fCurrLayer = canvas->fMCRec->fTopLayer;
222        fSkipEmptyClips = skipEmptyClips;
223    }
224
225    bool next() {
226        // skip over recs with empty clips
227        if (fSkipEmptyClips) {
228            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
229                fCurrLayer = fCurrLayer->fNext;
230            }
231        }
232
233        if (NULL != fCurrLayer) {
234            const DeviceCM* rec = fCurrLayer;
235
236            fMatrix = rec->fMatrix;
237            fClip   = &rec->fClip;
238            fDevice = rec->fDevice;
239            fBitmap = &fDevice->accessBitmap(true);
240            fLayerX = rec->fX;
241            fLayerY = rec->fY;
242            fPaint  = rec->fPaint;
243            SkDEBUGCODE(this->validate();)
244
245            fCurrLayer = rec->fNext;
246            if (fBounder) {
247                fBounder->setClip(fClip);
248            }
249
250            // fCurrLayer may be NULL now
251
252            fCanvas->prepareForDeviceDraw(fDevice);
253            return true;
254        }
255        return false;
256    }
257
258    int getX() const { return fLayerX; }
259    int getY() const { return fLayerY; }
260    SkDevice* getDevice() const { return fDevice; }
261    const SkMatrix& getMatrix() const { return *fMatrix; }
262    const SkRegion& getClip() const { return *fClip; }
263    const SkPaint* getPaint() const { return fPaint; }
264private:
265    SkCanvas*       fCanvas;
266    const DeviceCM* fCurrLayer;
267    const SkPaint*  fPaint;     // May be null.
268    int             fLayerX;
269    int             fLayerY;
270    SkBool8         fSkipEmptyClips;
271
272    typedef SkDraw INHERITED;
273};
274
275/////////////////////////////////////////////////////////////////////////////
276
277class AutoDrawLooper {
278public:
279    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t)
280            : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) {
281        if ((fLooper = paint.getLooper()) != NULL) {
282            fLooper->init(canvas, (SkPaint*)&paint);
283        } else {
284            fOnce = true;
285        }
286        fFilter = canvas->getDrawFilter();
287        fNeedFilterRestore = false;
288    }
289
290    ~AutoDrawLooper() {
291        if (fNeedFilterRestore) {
292            SkASSERT(fFilter);
293            fFilter->restore(fCanvas, fPaint, fType);
294        }
295        if (NULL != fLooper) {
296            fLooper->restore();
297        }
298    }
299
300    bool next() {
301        SkDrawFilter* filter = fFilter;
302
303        // if we drew earlier with a filter, then we need to restore first
304        if (fNeedFilterRestore) {
305            SkASSERT(filter);
306            filter->restore(fCanvas, fPaint, fType);
307            fNeedFilterRestore = false;
308        }
309
310        bool result;
311
312        if (NULL != fLooper) {
313            result = fLooper->next();
314        } else {
315            result = fOnce;
316            fOnce = false;
317        }
318
319        // if we're gonna draw, give the filter a chance to do its work
320        if (result && NULL != filter) {
321            fNeedFilterRestore = result = filter->filter(fCanvas, fPaint,
322                                                         fType);
323        }
324        return result;
325    }
326
327private:
328    SkDrawLooper*   fLooper;
329    SkDrawFilter*   fFilter;
330    SkCanvas*       fCanvas;
331    SkPaint*        fPaint;
332    SkDrawFilter::Type  fType;
333    bool            fOnce;
334    bool            fNeedFilterRestore;
335
336};
337
338/*  Stack helper for managing a SkBounder. In the destructor, if we were
339    given a bounder, we call its commit() method, signifying that we are
340    done accumulating bounds for that draw.
341*/
342class SkAutoBounderCommit {
343public:
344    SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
345    ~SkAutoBounderCommit() {
346        if (NULL != fBounder) {
347            fBounder->commit();
348        }
349    }
350private:
351    SkBounder*  fBounder;
352};
353
354#include "SkColorPriv.h"
355
356class AutoValidator {
357public:
358    AutoValidator(SkDevice* device) : fDevice(device) {}
359    ~AutoValidator() {
360#ifdef SK_DEBUG
361        const SkBitmap& bm = fDevice->accessBitmap(false);
362        if (bm.config() == SkBitmap::kARGB_4444_Config) {
363            for (int y = 0; y < bm.height(); y++) {
364                const SkPMColor16* p = bm.getAddr16(0, y);
365                for (int x = 0; x < bm.width(); x++) {
366                    SkPMColor16 c = p[x];
367                    SkPMColor16Assert(c);
368                }
369            }
370        }
371#endif
372    }
373private:
374    SkDevice* fDevice;
375};
376
377////////// macros to place around the internal draw calls //////////////////
378
379#define ITER_BEGIN(paint, type)                                     \
380/*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
381    AutoDrawLooper  looper(this, paint, type);                      \
382    while (looper.next()) {                                         \
383        SkAutoBounderCommit ac(fBounder);                           \
384        SkDrawIter          iter(this);
385
386#define ITER_END    }
387
388////////////////////////////////////////////////////////////////////////////
389
390SkDevice* SkCanvas::init(SkDevice* device) {
391    fBounder = NULL;
392    fLocalBoundsCompareTypeDirty = true;
393
394    fMCRec = (MCRec*)fMCStack.push_back();
395    new (fMCRec) MCRec(NULL, 0);
396
397    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL));
398    fMCRec->fTopLayer = fMCRec->fLayer;
399    fMCRec->fNext = NULL;
400
401    return this->setDevice(device);
402}
403
404SkCanvas::SkCanvas(SkDevice* device)
405        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
406    inc_canvas();
407
408    this->init(device);
409}
410
411SkCanvas::SkCanvas(const SkBitmap& bitmap)
412        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
413    inc_canvas();
414
415    this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
416}
417
418SkCanvas::~SkCanvas() {
419    // free up the contents of our deque
420    this->restoreToCount(1);    // restore everything but the last
421    this->internalRestore();    // restore the last, since we're going away
422
423    fBounder->safeUnref();
424
425    dec_canvas();
426}
427
428SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
429    SkRefCnt_SafeAssign(fBounder, bounder);
430    return bounder;
431}
432
433SkDrawFilter* SkCanvas::getDrawFilter() const {
434    return fMCRec->fFilter;
435}
436
437SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
438    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
439    return filter;
440}
441
442///////////////////////////////////////////////////////////////////////////////
443
444SkDevice* SkCanvas::getDevice() const {
445    // return root device
446    SkDeque::Iter   iter(fMCStack);
447    MCRec*          rec = (MCRec*)iter.next();
448    SkASSERT(rec && rec->fLayer);
449    return rec->fLayer->fDevice;
450}
451
452SkDevice* SkCanvas::setDevice(SkDevice* device) {
453    // return root device
454    SkDeque::Iter   iter(fMCStack);
455    MCRec*          rec = (MCRec*)iter.next();
456    SkASSERT(rec && rec->fLayer);
457    SkDevice*       rootDevice = rec->fLayer->fDevice;
458
459    if (rootDevice == device) {
460        return device;
461    }
462
463    /* Notify the devices that they are going in/out of scope, so they can do
464       things like lock/unlock their pixels, etc.
465    */
466    if (device) {
467        device->lockPixels();
468    }
469    if (rootDevice) {
470        rootDevice->unlockPixels();
471    }
472
473    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
474    rootDevice = device;
475
476    fDeviceCMDirty = true;
477
478    /*  Now we update our initial region to have the bounds of the new device,
479        and then intersect all of the clips in our stack with these bounds,
480        to ensure that we can't draw outside of the device's bounds (and trash
481                                                                     memory).
482
483    NOTE: this is only a partial-fix, since if the new device is larger than
484        the previous one, we don't know how to "enlarge" the clips in our stack,
485        so drawing may be artificially restricted. Without keeping a history of
486        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
487        reconstruct the correct clips, so this approximation will have to do.
488        The caller really needs to restore() back to the base if they want to
489        accurately take advantage of the new device bounds.
490    */
491
492    if (NULL == device) {
493        rec->fRegion->setEmpty();
494        while ((rec = (MCRec*)iter.next()) != NULL) {
495            (void)rec->fRegion->setEmpty();
496        }
497    } else {
498        // compute our total bounds for all devices
499        SkIRect bounds;
500
501        bounds.set(0, 0, device->width(), device->height());
502
503        // now jam our 1st clip to be bounds, and intersect the rest with that
504        rec->fRegion->setRect(bounds);
505        while ((rec = (MCRec*)iter.next()) != NULL) {
506            (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op);
507        }
508    }
509    return device;
510}
511
512SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
513    SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
514    device->unref();
515    return device;
516}
517
518//////////////////////////////////////////////////////////////////////////////
519
520bool SkCanvas::getViewport(SkIPoint* size) const {
521    return false;
522}
523
524bool SkCanvas::setViewport(int width, int height) {
525    return false;
526}
527
528void SkCanvas::updateDeviceCMCache() {
529    if (fDeviceCMDirty) {
530        const SkMatrix& totalMatrix = this->getTotalMatrix();
531        const SkRegion& totalClip = this->getTotalClip();
532        DeviceCM*       layer = fMCRec->fTopLayer;
533
534        if (NULL == layer->fNext) {   // only one layer
535            layer->updateMC(totalMatrix, totalClip, NULL);
536        } else {
537            SkRegion clip;
538            clip = totalClip;  // make a copy
539            do {
540                layer->updateMC(totalMatrix, clip, &clip);
541            } while ((layer = layer->fNext) != NULL);
542        }
543        fDeviceCMDirty = false;
544    }
545}
546
547void SkCanvas::prepareForDeviceDraw(SkDevice* device) {
548    SkASSERT(device);
549    device->gainFocus(this);
550}
551
552///////////////////////////////////////////////////////////////////////////////
553
554int SkCanvas::internalSave(SaveFlags flags) {
555    int saveCount = this->getSaveCount(); // record this before the actual save
556
557    MCRec* newTop = (MCRec*)fMCStack.push_back();
558    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
559
560    newTop->fNext = fMCRec;
561    fMCRec = newTop;
562
563    return saveCount;
564}
565
566int SkCanvas::save(SaveFlags flags) {
567    // call shared impl
568    return this->internalSave(flags);
569}
570
571#define C32MASK (1 << SkBitmap::kARGB_8888_Config)
572#define C16MASK (1 << SkBitmap::kRGB_565_Config)
573#define C8MASK  (1 << SkBitmap::kA8_Config)
574
575static SkBitmap::Config resolve_config(SkCanvas* canvas,
576                                       const SkIRect& bounds,
577                                       SkCanvas::SaveFlags flags,
578                                       bool* isOpaque) {
579    *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
580
581#if 0
582    // loop through and union all the configs we may draw into
583    uint32_t configMask = 0;
584    for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
585    {
586        SkDevice* device = canvas->getLayerDevice(i);
587        if (device->intersects(bounds))
588            configMask |= 1 << device->config();
589    }
590
591    // if the caller wants alpha or fullcolor, we can't return 565
592    if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
593                 SkCanvas::kHasAlphaLayer_SaveFlag))
594        configMask &= ~C16MASK;
595
596    switch (configMask) {
597    case C8MASK:    // if we only have A8, return that
598        return SkBitmap::kA8_Config;
599
600    case C16MASK:   // if we only have 565, return that
601        return SkBitmap::kRGB_565_Config;
602
603    default:
604        return SkBitmap::kARGB_8888_Config; // default answer
605    }
606#else
607    return SkBitmap::kARGB_8888_Config; // default answer
608#endif
609}
610
611static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
612    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
613}
614
615int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
616                        SaveFlags flags) {
617    // do this before we create the layer. We don't call the public save() since
618    // that would invoke a possibly overridden virtual
619    int count = this->internalSave(flags);
620
621    fDeviceCMDirty = true;
622
623    SkIRect         ir;
624    const SkIRect&  clipBounds = this->getTotalClip().getBounds();
625
626    if (NULL != bounds) {
627        SkRect r;
628
629        this->getTotalMatrix().mapRect(&r, *bounds);
630        r.roundOut(&ir);
631        // early exit if the layer's bounds are clipped out
632        if (!ir.intersect(clipBounds)) {
633            if (bounds_affects_clip(flags))
634                fMCRec->fRegion->setEmpty();
635            return count;
636        }
637    } else {    // no user bounds, so just use the clip
638        ir = clipBounds;
639    }
640
641    // early exit if the clip is now empty
642    if (bounds_affects_clip(flags) &&
643        !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) {
644        return count;
645    }
646
647    bool isOpaque;
648    SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
649
650    SkDevice* device = this->createDevice(config, ir.width(), ir.height(),
651                                          isOpaque, true);
652    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
653    device->unref();
654
655    layer->fNext = fMCRec->fTopLayer;
656    fMCRec->fLayer = layer;
657    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
658
659    return count;
660}
661
662int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
663                             SaveFlags flags) {
664    if (0xFF == alpha) {
665        return this->saveLayer(bounds, NULL, flags);
666    } else {
667        SkPaint tmpPaint;
668        tmpPaint.setAlpha(alpha);
669        return this->saveLayer(bounds, &tmpPaint, flags);
670    }
671}
672
673void SkCanvas::restore() {
674    // check for underflow
675    if (fMCStack.count() > 1) {
676        this->internalRestore();
677    }
678}
679
680void SkCanvas::internalRestore() {
681    SkASSERT(fMCStack.count() != 0);
682
683    fDeviceCMDirty = true;
684    fLocalBoundsCompareTypeDirty = true;
685
686	// reserve our layer (if any)
687    DeviceCM* layer = fMCRec->fLayer;   // may be null
688    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
689    fMCRec->fLayer = NULL;
690
691    // now do the normal restore()
692    fMCRec->~MCRec();       // balanced in save()
693    fMCStack.pop_back();
694    fMCRec = (MCRec*)fMCStack.back();
695
696    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
697        since if we're being recorded, we don't want to record this (the
698        recorder will have already recorded the restore).
699    */
700    if (NULL != layer) {
701        if (layer->fNext) {
702            this->drawDevice(layer->fDevice, layer->fX, layer->fY,
703                             layer->fPaint);
704            // reset this, since drawDevice will have set it to true
705            fDeviceCMDirty = true;
706        }
707        SkDELETE(layer);
708	}
709}
710
711int SkCanvas::getSaveCount() const {
712    return fMCStack.count();
713}
714
715void SkCanvas::restoreToCount(int count) {
716    // sanity check
717    if (count < 1) {
718        count = 1;
719    }
720    while (fMCStack.count() > count) {
721        this->restore();
722    }
723}
724
725/////////////////////////////////////////////////////////////////////////////
726
727// can't draw it if its empty, or its too big for a fixed-point width or height
728static bool reject_bitmap(const SkBitmap& bitmap) {
729    return  bitmap.width() <= 0 || bitmap.height() <= 0 ||
730            bitmap.width() > 32767 || bitmap.height() > 32767;
731}
732
733void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
734                                const SkMatrix& matrix, const SkPaint* paint) {
735    if (reject_bitmap(bitmap)) {
736        return;
737    }
738
739    if (NULL == paint) {
740        SkPaint tmpPaint;
741        this->commonDrawBitmap(bitmap, matrix, tmpPaint);
742    } else {
743        this->commonDrawBitmap(bitmap, matrix, *paint);
744    }
745}
746
747void SkCanvas::drawDevice(SkDevice* device, int x, int y,
748                          const SkPaint* paint) {
749    SkPaint tmp;
750    if (NULL == paint) {
751        tmp.setDither(true);
752        paint = &tmp;
753    }
754
755    ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
756    while (iter.next()) {
757        iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
758                                 *paint);
759    }
760    ITER_END
761}
762
763/////////////////////////////////////////////////////////////////////////////
764
765bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
766    fDeviceCMDirty = true;
767    fLocalBoundsCompareTypeDirty = true;
768    return fMCRec->fMatrix->preTranslate(dx, dy);
769}
770
771bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
772    fDeviceCMDirty = true;
773    fLocalBoundsCompareTypeDirty = true;
774    return fMCRec->fMatrix->preScale(sx, sy);
775}
776
777bool SkCanvas::rotate(SkScalar degrees) {
778    fDeviceCMDirty = true;
779    fLocalBoundsCompareTypeDirty = true;
780    return fMCRec->fMatrix->preRotate(degrees);
781}
782
783bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
784    fDeviceCMDirty = true;
785    fLocalBoundsCompareTypeDirty = true;
786    return fMCRec->fMatrix->preSkew(sx, sy);
787}
788
789bool SkCanvas::concat(const SkMatrix& matrix) {
790    fDeviceCMDirty = true;
791    fLocalBoundsCompareTypeDirty = true;
792    return fMCRec->fMatrix->preConcat(matrix);
793}
794
795void SkCanvas::setMatrix(const SkMatrix& matrix) {
796    fDeviceCMDirty = true;
797    fLocalBoundsCompareTypeDirty = true;
798    *fMCRec->fMatrix = matrix;
799}
800
801// this is not virtual, so it must call a virtual method so that subclasses
802// will see its action
803void SkCanvas::resetMatrix() {
804    SkMatrix matrix;
805
806    matrix.reset();
807    this->setMatrix(matrix);
808}
809
810//////////////////////////////////////////////////////////////////////////////
811
812bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
813    fDeviceCMDirty = true;
814    fLocalBoundsCompareTypeDirty = true;
815
816    if (fMCRec->fMatrix->rectStaysRect()) {
817        // for these simpler matrices, we can stay a rect ever after applying
818        // the matrix. This means we don't have to a) make a path, and b) tell
819        // the region code to scan-convert the path, only to discover that it
820        // is really just a rect.
821        SkRect      r;
822        SkIRect     ir;
823
824        fMCRec->fMatrix->mapRect(&r, rect);
825        r.round(&ir);
826        return fMCRec->fRegion->op(ir, op);
827    } else {
828        // since we're rotate or some such thing, we convert the rect to a path
829        // and clip against that, since it can handle any matrix. However, to
830        // avoid recursion in the case where we are subclassed (e.g. Pictures)
831        // we explicitly call "our" version of clipPath.
832        SkPath  path;
833
834        path.addRect(rect);
835        return this->SkCanvas::clipPath(path, op);
836    }
837}
838
839bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
840    fDeviceCMDirty = true;
841    fLocalBoundsCompareTypeDirty = true;
842
843    SkPath devPath;
844    path.transform(*fMCRec->fMatrix, &devPath);
845
846    if (SkRegion::kIntersect_Op == op) {
847        return fMCRec->fRegion->setPath(devPath, *fMCRec->fRegion);
848    } else {
849        SkRegion base;
850        const SkBitmap& bm = this->getDevice()->accessBitmap(false);
851        base.setRect(0, 0, bm.width(), bm.height());
852
853        if (SkRegion::kReplace_Op == op) {
854            return fMCRec->fRegion->setPath(devPath, base);
855        } else {
856            SkRegion rgn;
857            rgn.setPath(devPath, base);
858            return fMCRec->fRegion->op(rgn, op);
859        }
860    }
861}
862
863bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
864    fDeviceCMDirty = true;
865    fLocalBoundsCompareTypeDirty = true;
866
867    return fMCRec->fRegion->op(rgn, op);
868}
869
870void SkCanvas::computeLocalClipBoundsCompareType() const {
871    SkRect r;
872
873    if (!this->getClipBounds(&r, kAA_EdgeType)) {
874        fLocalBoundsCompareType.setEmpty();
875    } else {
876        fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft),
877                                    SkScalarToCompareType(r.fTop),
878                                    SkScalarToCompareType(r.fRight),
879                                    SkScalarToCompareType(r.fBottom));
880    }
881}
882
883/*  current impl ignores edgetype, and relies on
884    getLocalClipBoundsCompareType(), which always returns a value assuming
885    antialiasing (worst case)
886 */
887bool SkCanvas::quickReject(const SkRect& rect, EdgeType) const {
888    if (fMCRec->fRegion->isEmpty()) {
889        return true;
890    }
891
892    const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
893
894    // for speed, do the most likely reject compares first
895    SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
896    SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
897    if (userT >= clipR.fBottom || userB <= clipR.fTop) {
898        return true;
899    }
900    SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
901    SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
902    if (userL >= clipR.fRight || userR <= clipR.fLeft) {
903        return true;
904    }
905    return false;
906}
907
908bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
909    return path.isEmpty() || this->quickReject(path.getBounds(), et);
910}
911
912bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
913    /*  current impl ignores edgetype, and relies on
914        getLocalClipBoundsCompareType(), which always returns a value assuming
915        antialiasing (worst case)
916     */
917
918    if (fMCRec->fRegion->isEmpty()) {
919        return true;
920    }
921
922    SkScalarCompareType userT = SkScalarToCompareType(top);
923    SkScalarCompareType userB = SkScalarToCompareType(bottom);
924
925    // check for invalid user Y coordinates (i.e. empty)
926    // reed: why do we need to do this check, since it slows us down?
927    if (userT >= userB) {
928        return true;
929    }
930
931    // check if we are above or below the local clip bounds
932    const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
933    return userT >= clipR.fBottom || userB <= clipR.fTop;
934}
935
936bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
937    const SkRegion& clip = *fMCRec->fRegion;
938    if (clip.isEmpty()) {
939        if (bounds) {
940            bounds->setEmpty();
941        }
942        return false;
943    }
944
945    SkMatrix inverse;
946    // if we can't invert the CTM, we can't return local clip bounds
947    if (!fMCRec->fMatrix->invert(&inverse)) {
948        return false;
949    }
950
951    if (NULL != bounds) {
952        SkRect   r;
953        // get the clip's bounds
954        const SkIRect& ibounds = clip.getBounds();
955        // adjust it outwards if we are antialiasing
956        int inset = (kAA_EdgeType == et);
957        r.iset(ibounds.fLeft - inset,  ibounds.fTop - inset,
958               ibounds.fRight + inset, ibounds.fBottom + inset);
959
960        // invert into local coordinates
961        inverse.mapRect(bounds, r);
962    }
963    return true;
964}
965
966const SkMatrix& SkCanvas::getTotalMatrix() const {
967    return *fMCRec->fMatrix;
968}
969
970const SkRegion& SkCanvas::getTotalClip() const {
971    return *fMCRec->fRegion;
972}
973
974///////////////////////////////////////////////////////////////////////////////
975
976SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
977                                 int height, bool isOpaque, bool isForLayer) {
978    SkBitmap bitmap;
979
980    bitmap.setConfig(config, width, height);
981    bitmap.setIsOpaque(isOpaque);
982
983    // should this happen in the device subclass?
984    bitmap.allocPixels();
985    if (!bitmap.isOpaque()) {
986        bitmap.eraseARGB(0, 0, 0, 0);
987    }
988
989    return SkNEW_ARGS(SkDevice, (bitmap));
990}
991
992//////////////////////////////////////////////////////////////////////////////
993//  These are the virtual drawing methods
994//////////////////////////////////////////////////////////////////////////////
995
996void SkCanvas::drawPaint(const SkPaint& paint) {
997    ITER_BEGIN(paint, SkDrawFilter::kPaint_Type)
998
999    while (iter.next()) {
1000        iter.fDevice->drawPaint(iter, paint);
1001    }
1002
1003    ITER_END
1004}
1005
1006void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1007                          const SkPaint& paint) {
1008    if ((long)count <= 0) {
1009        return;
1010    }
1011
1012    SkASSERT(pts != NULL);
1013
1014    ITER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1015
1016    while (iter.next()) {
1017        iter.fDevice->drawPoints(iter, mode, count, pts, paint);
1018    }
1019
1020    ITER_END
1021}
1022
1023void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1024    if (paint.canComputeFastBounds()) {
1025        SkRect storage;
1026        if (this->quickReject(paint.computeFastBounds(r, &storage),
1027                              paint2EdgeType(&paint))) {
1028            return;
1029        }
1030    }
1031
1032    ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
1033
1034    while (iter.next()) {
1035        iter.fDevice->drawRect(iter, r, paint);
1036    }
1037
1038    ITER_END
1039}
1040
1041void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1042    if (paint.canComputeFastBounds()) {
1043        SkRect storage;
1044        const SkRect& bounds = path.getBounds();
1045        if (this->quickReject(paint.computeFastBounds(bounds, &storage),
1046                              paint2EdgeType(&paint))) {
1047            return;
1048        }
1049    }
1050
1051    ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
1052
1053    while (iter.next()) {
1054        iter.fDevice->drawPath(iter, path, paint);
1055    }
1056
1057    ITER_END
1058}
1059
1060void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1061                          const SkPaint* paint) {
1062    SkDEBUGCODE(bitmap.validate();)
1063
1064    if (NULL == paint || (paint->getMaskFilter() == NULL)) {
1065        SkRect fastBounds;
1066        fastBounds.set(x, y,
1067                       x + SkIntToScalar(bitmap.width()),
1068                       y + SkIntToScalar(bitmap.height()));
1069        if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
1070            return;
1071        }
1072    }
1073
1074    SkMatrix matrix;
1075    matrix.setTranslate(x, y);
1076    this->internalDrawBitmap(bitmap, matrix, paint);
1077}
1078
1079void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
1080                              const SkRect& dst, const SkPaint* paint) {
1081    if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1082        return;
1083    }
1084
1085    // do this now, to avoid the cost of calling extract for RLE bitmaps
1086    if (this->quickReject(dst, paint2EdgeType(paint))) {
1087        return;
1088    }
1089
1090    SkBitmap        tmp;    // storage if we need a subset of bitmap
1091    const SkBitmap* bitmapPtr = &bitmap;
1092
1093    if (NULL != src) {
1094        if (!bitmap.extractSubset(&tmp, *src)) {
1095            return;     // extraction failed
1096        }
1097        bitmapPtr = &tmp;
1098    }
1099
1100    SkScalar width = SkIntToScalar(bitmapPtr->width());
1101    SkScalar height = SkIntToScalar(bitmapPtr->height());
1102    SkMatrix matrix;
1103
1104    if (dst.width() == width && dst.height() == height) {
1105        matrix.setTranslate(dst.fLeft, dst.fTop);
1106    } else {
1107        SkRect tmpSrc;
1108        tmpSrc.set(0, 0, width, height);
1109        matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1110    }
1111    this->internalDrawBitmap(*bitmapPtr, matrix, paint);
1112}
1113
1114void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1115                                const SkPaint* paint) {
1116    SkDEBUGCODE(bitmap.validate();)
1117    this->internalDrawBitmap(bitmap, matrix, paint);
1118}
1119
1120void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
1121                                const SkPaint& paint) {
1122    SkDEBUGCODE(bitmap.validate();)
1123
1124    ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1125
1126    while (iter.next()) {
1127        iter.fDevice->drawBitmap(iter, bitmap, matrix, paint);
1128    }
1129
1130    ITER_END
1131}
1132
1133void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1134                          const SkPaint* paint) {
1135    SkDEBUGCODE(bitmap.validate();)
1136
1137    if (reject_bitmap(bitmap)) {
1138        return;
1139    }
1140
1141    SkPaint tmp;
1142    if (NULL == paint) {
1143        paint = &tmp;
1144    }
1145
1146    ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1147
1148    while (iter.next()) {
1149        iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
1150                                 *paint);
1151    }
1152    ITER_END
1153}
1154
1155void SkCanvas::drawText(const void* text, size_t byteLength,
1156                        SkScalar x, SkScalar y, const SkPaint& paint) {
1157    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1158
1159    while (iter.next()) {
1160        iter.fDevice->drawText(iter, text, byteLength, x, y, paint);
1161    }
1162
1163    ITER_END
1164}
1165
1166void SkCanvas::drawPosText(const void* text, size_t byteLength,
1167                           const SkPoint pos[], const SkPaint& paint) {
1168    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1169
1170    while (iter.next()) {
1171        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1172                                  paint);
1173    }
1174
1175    ITER_END
1176}
1177
1178void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1179                            const SkScalar xpos[], SkScalar constY,
1180                            const SkPaint& paint) {
1181    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1182
1183    while (iter.next()) {
1184        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1185                                  paint);
1186    }
1187
1188    ITER_END
1189}
1190
1191void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1192                              const SkPath& path, const SkMatrix* matrix,
1193                              const SkPaint& paint) {
1194    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
1195
1196    while (iter.next()) {
1197        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1198                                     matrix, paint);
1199    }
1200
1201    ITER_END
1202}
1203
1204void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1205                            const SkPoint verts[], const SkPoint texs[],
1206                            const SkColor colors[], SkXfermode* xmode,
1207                            const uint16_t indices[], int indexCount,
1208                            const SkPaint& paint) {
1209    ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
1210
1211    while (iter.next()) {
1212        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1213                                   colors, xmode, indices, indexCount, paint);
1214    }
1215
1216    ITER_END
1217}
1218
1219//////////////////////////////////////////////////////////////////////////////
1220// These methods are NOT virtual, and therefore must call back into virtual
1221// methods, rather than actually drawing themselves.
1222//////////////////////////////////////////////////////////////////////////////
1223
1224void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1225                        SkPorterDuff::Mode mode) {
1226    SkPaint paint;
1227
1228    paint.setARGB(a, r, g, b);
1229    if (SkPorterDuff::kSrcOver_Mode != mode) {
1230        paint.setPorterDuffXfermode(mode);
1231    }
1232    this->drawPaint(paint);
1233}
1234
1235void SkCanvas::drawColor(SkColor c, SkPorterDuff::Mode mode) {
1236    SkPaint paint;
1237
1238    paint.setColor(c);
1239    if (SkPorterDuff::kSrcOver_Mode != mode) {
1240        paint.setPorterDuffXfermode(mode);
1241    }
1242    this->drawPaint(paint);
1243}
1244
1245void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
1246    SkPoint pt;
1247
1248    pt.set(x, y);
1249    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1250}
1251
1252void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
1253    SkPoint pt;
1254    SkPaint paint;
1255
1256    pt.set(x, y);
1257    paint.setColor(color);
1258    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
1259}
1260
1261void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
1262                        const SkPaint& paint) {
1263    SkPoint pts[2];
1264
1265    pts[0].set(x0, y0);
1266    pts[1].set(x1, y1);
1267    this->drawPoints(kLines_PointMode, 2, pts, paint);
1268}
1269
1270void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
1271                              SkScalar right, SkScalar bottom,
1272                              const SkPaint& paint) {
1273    SkRect  r;
1274
1275    r.set(left, top, right, bottom);
1276    this->drawRect(r, paint);
1277}
1278
1279void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
1280                          const SkPaint& paint) {
1281    if (radius < 0) {
1282        radius = 0;
1283    }
1284
1285    SkRect  r;
1286    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
1287
1288    if (paint.canComputeFastBounds()) {
1289        SkRect storage;
1290        if (this->quickReject(paint.computeFastBounds(r, &storage),
1291                              paint2EdgeType(&paint))) {
1292            return;
1293        }
1294    }
1295
1296    SkPath  path;
1297    path.addOval(r);
1298    this->drawPath(path, paint);
1299}
1300
1301void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
1302                             const SkPaint& paint) {
1303    if (rx > 0 && ry > 0) {
1304        if (paint.canComputeFastBounds()) {
1305            SkRect storage;
1306            if (this->quickReject(paint.computeFastBounds(r, &storage),
1307                                  paint2EdgeType(&paint))) {
1308                return;
1309            }
1310        }
1311
1312        SkPath  path;
1313        path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
1314        this->drawPath(path, paint);
1315    } else {
1316        this->drawRect(r, paint);
1317    }
1318}
1319
1320void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1321    if (paint.canComputeFastBounds()) {
1322        SkRect storage;
1323        if (this->quickReject(paint.computeFastBounds(oval, &storage),
1324                              paint2EdgeType(&paint))) {
1325            return;
1326        }
1327    }
1328
1329    SkPath  path;
1330    path.addOval(oval);
1331    this->drawPath(path, paint);
1332}
1333
1334void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
1335                       SkScalar sweepAngle, bool useCenter,
1336                       const SkPaint& paint) {
1337    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
1338        this->drawOval(oval, paint);
1339    } else {
1340        SkPath  path;
1341        if (useCenter) {
1342            path.moveTo(oval.centerX(), oval.centerY());
1343        }
1344        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
1345        if (useCenter) {
1346            path.close();
1347        }
1348        this->drawPath(path, paint);
1349    }
1350}
1351
1352void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
1353                                const SkPath& path, SkScalar hOffset,
1354                                SkScalar vOffset, const SkPaint& paint) {
1355    SkMatrix    matrix;
1356
1357    matrix.setTranslate(hOffset, vOffset);
1358    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
1359}
1360
1361///////////////////////////////////////////////////////////////////////////////
1362
1363void SkCanvas::drawPicture(SkPicture& picture) {
1364    int saveCount = save();
1365    picture.draw(this);
1366    restoreToCount(saveCount);
1367}
1368
1369void SkCanvas::drawShape(SkShape* shape) {
1370    // shape baseclass takes care of save/restore
1371    shape->draw(this);
1372}
1373
1374///////////////////////////////////////////////////////////////////////////////
1375///////////////////////////////////////////////////////////////////////////////
1376
1377SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
1378    // need COMPILE_TIME_ASSERT
1379    SkASSERT(sizeof(fStorage) >= sizeof(SkDrawIter));
1380
1381    SkASSERT(canvas);
1382
1383    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
1384    fDone = !fImpl->next();
1385}
1386
1387SkCanvas::LayerIter::~LayerIter() {
1388    fImpl->~SkDrawIter();
1389}
1390
1391void SkCanvas::LayerIter::next() {
1392    fDone = !fImpl->next();
1393}
1394
1395SkDevice* SkCanvas::LayerIter::device() const {
1396    return fImpl->getDevice();
1397}
1398
1399const SkMatrix& SkCanvas::LayerIter::matrix() const {
1400    return fImpl->getMatrix();
1401}
1402
1403const SkPaint& SkCanvas::LayerIter::paint() const {
1404    const SkPaint* paint = fImpl->getPaint();
1405    if (NULL == paint) {
1406        paint = &fDefaultPaint;
1407    }
1408    return *paint;
1409}
1410
1411const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
1412int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
1413int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
1414
1415