SkCanvas.cpp revision 819c921b0445fa9f45f18d4a560603cd9fde6ba4
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Copyright (C) 2006-2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Licensed under the Apache License, Version 2.0 (the "License");
58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * you may not use this file except in compliance with the License.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * You may obtain a copy of the License at
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *      http://www.apache.org/licenses/LICENSE-2.0
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Unless required by applicable law or agreed to in writing, software
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * distributed under the License is distributed on an "AS IS" BASIS,
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * See the License for the specific language governing permissions and
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * limitations under the License.
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDevice.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalarCompare.h"
25f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com#include "SkShape.h"
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <new>
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Helpers for computing fast bounds for quickReject tests
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) {
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return paint != NULL && paint->isAntiAlias() ?
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each SkDevice that the user installs.
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDevice*           fDevice;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion            fClip;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix*     fMatrix;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	SkPaint*			fPaint;	// may be null (in the future)
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int16_t             fX, fY; // relative to base matrix/clip
77f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    // optional, related to canvas' external matrix
78f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    const SkMatrix*     fMVMatrix;
79f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    const SkMatrix*     fExtMatrix;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            : fNext(NULL) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != device) {
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->lockPixels();
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX = SkToS16(x);
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY = SkToS16(y);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	}
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	~DeviceCM() {
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fDevice) {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unlockPixels();
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com		SkDELETE(fPaint);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	}
1004b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip,
10246799cd9f0bded51a189d77731b25af159ab4609reed@google.com                  const SkClipStack& clipStack, SkRegion* updateClip) {
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int x = fX;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int y = fY;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1074b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fClip.op(0, 0, width, height, SkRegion::kIntersect_Op);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            updateClip->op(x, y, x + width, y + height,
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12946799cd9f0bded51a189d77731b25af159ab4609reed@google.com        fDevice->setMatrixClip(*fMatrix, fClip, clipStack);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
138f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        // default is to assume no external matrix
139f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fMVMatrix = NULL;
140f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fExtMatrix = NULL;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
142f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
143f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    // can only be called after calling updateMC()
144f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) {
145f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fMVMatrixStorage.setConcat(extI, *fMatrix);
146f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fMVMatrix = &fMVMatrixStorage;
147f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas)
148f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
149f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void translateClip() {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fX | fY) {
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip.translate(fX, fY);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    SkMatrix    fMatrixStorage, fMVMatrixStorage;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec*          fNext;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix*       fMatrix;    // points to either fMatrixStorage or prev MCRec
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion*       fRegion;    // points to either fRegionStorage or prev MCRec
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDrawFilter*   fFilter;    // the current filter (or null)
1734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*   fLayer;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*	fTopLayer;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec(const MCRec* prev, int flags) {
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != prev) {
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kMatrix_SaveFlag) {
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrixStorage = *prev->fMatrix;
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = &fMatrixStorage;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = prev->fMatrix;
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kClip_SaveFlag) {
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRegionStorage = *prev->fRegion;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRegion = &fRegionStorage;
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRegion = prev->fRegion;
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter = prev->fFilter;
20082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkSafeRef(fFilter);
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer = prev->fTopLayer;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {   // no prev
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.reset();
2054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix     = &fMatrixStorage;
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRegion     = &fRegionStorage;
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter     = NULL;
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer   = NULL;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
21782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    fMatrixStorage;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion    fRegionStorage;
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCanvas = canvas;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBounder = canvas->getBounder();
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fSkipEmptyClips = skipEmptyClips;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fCurrLayer) {
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const DeviceCM* rec = fCurrLayer;
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip   = &rec->fClip;
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLayerX = rec->fX;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLayerY = rec->fY;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
256f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            fMVMatrix = rec->fMVMatrix;
257f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            fExtMatrix = rec->fExtMatrix;
258f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fBounder) {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fBounder->setClip(fClip);
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
265199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
266f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip);
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int getX() const { return fLayerX; }
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int getY() const { return fLayerY; }
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDevice* getDevice() const { return fDevice; }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int             fLayerX;
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int             fLayerY;
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t)
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) {
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((fLooper = paint.getLooper()) != NULL) {
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLooper->init(canvas, (SkPaint*)&paint);
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fOnce = true;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fNeedFilterRestore = false;
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~AutoDrawLooper() {
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fNeedFilterRestore) {
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(fFilter);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter->restore(fCanvas, fPaint, fType);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fLooper) {
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLooper->restore();
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3134b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawFilter* filter = fFilter;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // if we drew earlier with a filter, then we need to restore first
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fNeedFilterRestore) {
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(filter);
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            filter->restore(fCanvas, fPaint, fType);
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fNeedFilterRestore = false;
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool result;
3254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fLooper) {
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result = fLooper->next();
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result = fOnce;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fOnce = false;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // if we're gonna draw, give the filter a chance to do its work
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (result && NULL != filter) {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fNeedFilterRestore = result = filter->filter(fCanvas, fPaint,
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                         fType);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return result;
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDrawLooper*   fLooper;
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDrawFilter*   fFilter;
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint*        fPaint;
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDrawFilter::Type  fType;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool            fOnce;
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool            fNeedFilterRestore;
3494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Stack helper for managing a SkBounder. In the destructor, if we were
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    given a bounder, we call its commit() method, signifying that we are
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    done accumulating bounds for that draw.
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit {
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoBounderCommit() {
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fBounder) {
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBounder->commit();
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBounder*  fBounder;
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoValidator {
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    AutoValidator(SkDevice* device) : fDevice(device) {}
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~AutoValidator() {
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkBitmap& bm = fDevice->accessBitmap(false);
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (bm.config() == SkBitmap::kARGB_4444_Config) {
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int y = 0; y < bm.height(); y++) {
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkPMColor16* p = bm.getAddr16(0, y);
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                for (int x = 0; x < bm.width(); x++) {
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkPMColor16 c = p[x];
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkPMColor16Assert(c);
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDevice* fDevice;
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define ITER_BEGIN(paint, type)                                     \
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*    AutoValidator   validator(fMCRec->fTopLayer->fDevice); */     \
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    AutoDrawLooper  looper(this, paint, type);                      \
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (looper.next()) {                                         \
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoBounderCommit ac(fBounder);                           \
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
3994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define ITER_END    }
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::init(SkDevice* device) {
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBounder = NULL;
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
407ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
408199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com    fLastDeviceToGainFocus = NULL;
409447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org    fDeviceCMDirty = false;
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (fMCRec) MCRec(NULL, 0);
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL));
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fNext = NULL;
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    fUseExternalMatrix = false;
419f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->setDevice(device);
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4238d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.orgSkCanvas::SkCanvas(SkDeviceFactory* factory)
4248d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
4258d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org          fDeviceFactory(factory) {
4268d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
4278d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
4288d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    if (!factory)
4298d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org        fDeviceFactory = SkNEW(SkRasterDeviceFactory);
4308d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
4318d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    this->init(NULL);
4328d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
4338d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(SkDevice* device)
4358d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
4368d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org          fDeviceFactory(device->getDeviceFactory()) {
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->init(device);
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap)
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
446f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
4478d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    fDeviceFactory = device->getDeviceFactory();
4488d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    this->init(device)->unref();
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4568d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    SkSafeUnref(fBounder);
457b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org    SkDELETE(fDeviceFactory);
458b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) {
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fBounder, bounder);
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return bounder;
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::getDevice() const {
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
4804c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
4814c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::setDevice(SkDevice* device) {
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
4884c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
4894c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDevice*       rootDevice = rec->fLayer->fDevice;
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice == device) {
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return device;
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /* Notify the devices that they are going in/out of scope, so they can do
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com       things like lock/unlock their pixels, etc.
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (device) {
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device->lockPixels();
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice) {
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rootDevice->unlockPixels();
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rootDevice = device;
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
5114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Now we update our initial region to have the bounds of the new device,
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and then intersect all of the clips in our stack with these bounds,
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to ensure that we can't draw outside of the device's bounds (and trash
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                     memory).
5164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this is only a partial-fix, since if the new device is larger than
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the previous one, we don't know how to "enlarge" the clips in our stack,
5194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        so drawing may be artificially restricted. Without keeping a history of
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reconstruct the correct clips, so this approximation will have to do.
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The caller really needs to restore() back to the base if they want to
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        accurately take advantage of the new device bounds.
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == device) {
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fRegion->setEmpty();
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while ((rec = (MCRec*)iter.next()) != NULL) {
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (void)rec->fRegion->setEmpty();
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5315c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com        fClipStack.reset();
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // compute our total bounds for all devices
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkIRect bounds;
5354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds.set(0, 0, device->width(), device->height());
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now jam our 1st clip to be bounds, and intersect the rest with that
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fRegion->setRect(bounds);
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while ((rec = (MCRec*)iter.next()) != NULL) {
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op);
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5435c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com        fClipStack.clipDevRect(bounds, SkRegion::kIntersect_Op);
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) {
549f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer)));
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
55551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    SkDevice* device = this->getDevice();
55651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    if (!device) {
55751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
55851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
55951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    return device->readPixels(srcRect, bitmap);
56051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
56151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
5624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.comSkDeviceFactory* SkCanvas::setDeviceFactory(SkDeviceFactory* factory) {
5634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com    SkDELETE(fDeviceFactory);
5644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com    fDeviceFactory = factory;
5659b2135a923c8344ef4c4f52907b7ffe4fc575136reed@google.com    return factory;
5664b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com}
5674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com//////////////////////////////////////////////////////////////////////////////
5694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
57051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(SkBitmap* bitmap) {
57151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    SkDevice* device = this->getDevice();
57251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    if (!device) {
57351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
57451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
57551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    SkIRect bounds;
57651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    bounds.set(0, 0, device->width(), device->height());
57751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    return this->readPixels(bounds, bitmap);
57851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
57951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
58051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
58151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    SkDevice* device = this->getDevice();
58251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    if (device) {
58351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        device->writePixels(bitmap, x, y);
58451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
58551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
58651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getViewport(SkIPoint* size) const {
59035fc62b960db6739b19c59576085663796951e47vandebo@chromium.org    if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0)
5918d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org        return false;
5928d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    if (size)
5938d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org        size->set(getDevice()->width(), getDevice()->height());
5948d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    return true;
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::setViewport(int width, int height) {
59835fc62b960db6739b19c59576085663796951e47vandebo@chromium.org    if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0)
5998d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org        return false;
600f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
601f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    this->setDevice(this->createDevice(SkBitmap::kARGB_8888_Config, width, height,
602f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                                       false, false))->unref();
6038d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    return true;
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkRegion& totalClip = this->getTotalClip();
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
6114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
61346799cd9f0bded51a189d77731b25af159ab4609reed@google.com            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
614f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            if (fUseExternalMatrix) {
615f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                layer->updateExternalMatrix(fExternalMatrix,
616f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                                            fExternalInverse);
617f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            }
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRegion clip;
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            clip = totalClip;  // make a copy
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
62246799cd9f0bded51a189d77731b25af159ab4609reed@google.com                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
623f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                if (fUseExternalMatrix) {
624f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                    layer->updateExternalMatrix(fExternalMatrix,
625f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                                                fExternalInverse);
626f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                }
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
633f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
634f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                                    const SkRegion& clip) {
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(device);
636199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com    if (fLastDeviceToGainFocus != device) {
637f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        device->gainFocus(this, matrix, clip);
638199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com        fLastDeviceToGainFocus = device;
639199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com    }
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) {
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = this->getSaveCount(); // record this before the actual save
6464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
6494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    newTop->fNext = fMCRec;
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
6524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6535c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fClipStack.save();
6545c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
6555c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return saveCount;
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) {
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // call shared impl
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->internalSave(flags);
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config)
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config)
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK  (1 << SkBitmap::kA8_Config)
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas,
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkIRect& bounds,
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       SkCanvas::SaveFlags flags,
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       bool* isOpaque) {
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // loop through and union all the configs we may draw into
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t configMask = 0;
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDevice* device = canvas->getLayerDevice(i);
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (device->intersects(bounds))
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            configMask |= 1 << device->config();
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if the caller wants alpha or fullcolor, we can't return 565
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkCanvas::kHasAlphaLayer_SaveFlag))
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        configMask &= ~C16MASK;
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (configMask) {
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case C8MASK:    // if we only have A8, return that
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkBitmap::kA8_Config;
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case C16MASK:   // if we only have 565, return that
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkBitmap::kRGB_565_Config;
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkBitmap::kARGB_8888_Config; // default answer
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkBitmap::kARGB_8888_Config; // default answer
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SaveFlags flags) {
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do this before we create the layer. We don't call the public save() since
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // that would invoke a possibly overridden virtual
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = this->internalSave(flags);
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect         ir;
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect&  clipBounds = this->getTotalClip().getBounds();
718f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    if (clipBounds.isEmpty()) {
719f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        return count;
720f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
7244b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->getTotalMatrix().mapRect(&r, *bounds);
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (bounds_affects_clip(flags))
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMCRec->fRegion->setEmpty();
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return count;
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7375c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // early exit if the clip is now empty
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bounds_affects_clip(flags) &&
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) {
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return count;
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool isOpaque;
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDevice* device = this->createDevice(config, ir.width(), ir.height(),
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          isOpaque, true);
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() {
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check for underflow
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCStack.count() > 1) {
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->internalRestore();
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
782ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fClipStack.restore();
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	// reserve our layer (if any)
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != layer) {
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->drawDevice(layer->fDevice, layer->fX, layer->fY,
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             layer->fPaint);
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // reset this, since drawDevice will have set it to true
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(layer);
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com	}
8085c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
8095c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const {
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCStack.count();
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) {
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // sanity check
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count < 1) {
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 1;
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (fMCStack.count() > count) {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->restore();
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) {
830a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com    return  bitmap.width() <= 0 || bitmap.height() <= 0
831a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#ifndef SK_ALLOW_OVER_32K_BITMAPS
832a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com            || bitmap.width() > 32767 || bitmap.height() > 32767
833a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#endif
834a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com            ;
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
837f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (reject_bitmap(bitmap)) {
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
845f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint);
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
847f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawDevice(SkDevice* device, int x, int y,
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp.setDither(true);
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8584b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                 *paint);
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) {
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
872ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preTranslate(dx, dy);
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) {
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
879ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preScale(sx, sy);
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) {
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
886ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preRotate(degrees);
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) {
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
893ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preSkew(sx, sy);
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) {
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
900ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preConcat(matrix);
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
907ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *fMCRec->fMatrix = matrix;
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
9154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
9235c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
9245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
927ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCRec->fMatrix->rectStaysRect()) {
93098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // for these simpler matrices, we can stay a rect ever after applying
93198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
93298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
93398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkIRect     ir;
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMCRec->fMatrix->mapRect(&r, rect);
9385c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com        fClipStack.clipDevRect(r, op);
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.round(&ir);
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fMCRec->fRegion->op(ir, op);
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
94298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // since we're rotate or some such thing, we convert the rect to a path
94398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
94498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
94598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
94998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        return this->SkCanvas::clipPath(path, op);
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
953819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRegion* currRgn,
954819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com                           const SkPath& devPath, SkRegion::Op op) {
955819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    if (SkRegion::kIntersect_Op == op) {
956819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        return currRgn->setPath(devPath, *currRgn);
957819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    } else {
958819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        SkRegion base;
959819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        const SkBitmap& bm = canvas->getDevice()->accessBitmap(false);
960819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        base.setRect(0, 0, bm.width(), bm.height());
961819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
962819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        if (SkRegion::kReplace_Op == op) {
963819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            return currRgn->setPath(devPath, base);
964819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        } else {
965819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            SkRegion rgn;
966819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            rgn.setPath(devPath, base);
967819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            return currRgn->op(rgn, op);
968819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
969819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
970819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
971819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
9735c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
9745c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
977ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path.transform(*fMCRec->fMatrix, &devPath);
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
9835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fClipStack.clipDevPath(devPath, op);
9845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
985819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    return clipPathHelper(this, fMCRec->fRegion, devPath, op);
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
9895c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
9905c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLocalBoundsCompareTypeDirty = true;
993ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    fLocalBoundsCompareTypeDirtyBW = true;
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9955c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
9965c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
9975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fClipStack.clipDevRect(rgn.getBounds());
9985c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fRegion->op(rgn, op);
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1002819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1003819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1004819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
1005819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    const SkDevice* device = this->getDevice();
1006819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1007819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1008819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkRegion clipRgn(ir);
1009819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1010819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkClipStack::B2FIter                iter(fClipStack);
1011819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    const SkClipStack::B2FIter::Clip*   clip;
1012819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    while ((clip = iter.next()) != NULL) {
1013819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        if (clip->fPath) {
1014819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            clipPathHelper(this, &clipRgn, *clip->fPath, clip->fOp);
1015819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        } else if (clip->fRect) {
1016819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            clip->fRect->round(&ir);
1017819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            clipRgn.op(ir, clip->fOp);
1018819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        } else {
1019819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com            break;
1020819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1021819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1022819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1023819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // now compare against the current rgn
1024819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    const SkRegion& rgn = this->getTotalClip();
1025819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkASSERT(rgn == clipRgn);
1026819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1027819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1028819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
10295c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
10305c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1031ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.comvoid SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect r;
1033ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType :
1034ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com            fLocalBoundsCompareTypeBW;
1035ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com
1036ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com    if (!this->getClipBounds(&r, et)) {
1037ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com        rCompare.setEmpty();
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1039ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com        rCompare.set(SkScalarToCompareType(r.fLeft),
1040ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com                     SkScalarToCompareType(r.fTop),
1041ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com                     SkScalarToCompareType(r.fRight),
1042ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com                     SkScalarToCompareType(r.fBottom));
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1046d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/*  current impl ignores edgetype, and relies on
1047d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    getLocalClipBoundsCompareType(), which always returns a value assuming
1048d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    antialiasing (worst case)
1049d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */
1050ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.combool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
1051116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
1052116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org    if (!rect.hasValidCoordinates())
1053116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1054116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCRec->fRegion->isEmpty()) {
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1059a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    if (fMCRec->fMatrix->getType() & SkMatrix::kPerspective_Mask) {
1060a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
1061a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        fMCRec->fMatrix->mapRect(&dst, rect);
1062a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkIRect idst;
1063a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        dst.roundOut(&idst);
1064a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds());
1065a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1066ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com        const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et);
1067d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1068a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1069a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
1070a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
1071a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        if (userT >= clipR.fBottom || userB <= clipR.fTop) {
1072a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1073a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1074a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
1075a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
1076a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        if (userL >= clipR.fRight || userR <= clipR.fLeft) {
1077a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1078a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1079a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
1084d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    return path.isEmpty() || this->quickReject(path.getBounds(), et);
10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  current impl ignores edgetype, and relies on
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        getLocalClipBoundsCompareType(), which always returns a value assuming
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialiasing (worst case)
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCRec->fRegion->isEmpty()) {
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1097aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkScalarCompareType userT = SkScalarToCompareType(top);
1098aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkScalarCompareType userB = SkScalarToCompareType(bottom);
10994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check for invalid user Y coordinates (i.e. empty)
1101d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    // reed: why do we need to do this check, since it slows us down?
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (userT >= userB) {
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check if we are above or below the local clip bounds
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return userT >= clipR.fBottom || userB <= clipR.fTop;
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& clip = *fMCRec->fRegion;
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (clip.isEmpty()) {
11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (bounds) {
11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bounds->setEmpty();
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1120d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1121d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
1122d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    if (!fMCRec->fMatrix->invert(&inverse)) {
112372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
112472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
112572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1126d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1127d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1128d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect   r;
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // get the clip's bounds
11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& ibounds = clip.getBounds();
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // adjust it outwards if we are antialiasing
11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int inset = (kAA_EdgeType == et);
11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.iset(ibounds.fLeft - inset,  ibounds.fTop - inset,
11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               ibounds.fRight + inset, ibounds.fBottom + inset);
11374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // invert into local coordinates
11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *fMCRec->fMatrix;
11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const {
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *fMCRec->fRegion;
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1152f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
1153f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    if (NULL == matrix || matrix->isIdentity()) {
1154f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        if (fUseExternalMatrix) {
1155f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            fDeviceCMDirty = true;
1156f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        }
1157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fUseExternalMatrix = false;
1158f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    } else {
1159f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fUseExternalMatrix = true;
1160f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fDeviceCMDirty = true;  // |= (fExternalMatrix != *matrix)
11614b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1162f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        fExternalMatrix = *matrix;
1163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        matrix->invert(&fExternalInverse);
1164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1165f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1167f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height,
1168f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                                 bool isOpaque, bool forLayer) {
1169f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer);
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) {
11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kPaint_Type)
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPaint(iter, paint);
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kPoint_Type)
11954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPoints(iter, mode, count, pts, paint);
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect storage;
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (this->quickReject(paint.computeFastBounds(r, &storage),
12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              paint2EdgeType(&paint))) {
12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawRect(iter, r, paint);
12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
1223d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        SkRect storage;
1224d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        const SkRect& bounds = path.getBounds();
1225d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        if (this->quickReject(paint.computeFastBounds(bounds, &storage),
12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              paint2EdgeType(&paint))) {
12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPath(iter, path, paint);
12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint || (paint->getMaskFilter() == NULL)) {
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect fastBounds;
12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fastBounds.set(x, y,
12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       x + SkIntToScalar(bitmap.width()),
12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       y + SkIntToScalar(bitmap.height()));
12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
1256f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkRect& dst, const SkPaint* paint) {
12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do this now, to avoid the cost of calling extract for RLE bitmaps
12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->quickReject(dst, paint2EdgeType(paint))) {
12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkBitmap* bitmapPtr = &bitmap;
12714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
1273878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com    SkRect tmpSrc;
1274878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com    if (src) {
1275878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        tmpSrc.set(*src);
1276878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        // if the extract process clipped off the top or left of the
1277878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        // original, we adjust for that here to get the position right.
1278878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        if (tmpSrc.fLeft > 0) {
1279878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com            tmpSrc.fRight -= tmpSrc.fLeft;
1280878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com            tmpSrc.fLeft = 0;
1281fead49e3c43e67cf9648ec1999b34da959e1e36breed@android.com        }
1282878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        if (tmpSrc.fTop > 0) {
1283878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com            tmpSrc.fBottom -= tmpSrc.fTop;
1284878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com            tmpSrc.fTop = 0;
1285878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        }
1286878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com    } else {
1287878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com        tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()),
1288878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com                   SkIntToScalar(bitmap.height()));
12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1290878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1291f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
1292f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    // ensure that src is "valid" before we pass it to our internal routines
1293f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    // and to SkDevice. i.e. sure it is contained inside the original bitmap.
1294f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    SkIRect tmpISrc;
1295f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    if (src) {
1296f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        tmpISrc.set(0, 0, bitmap.width(), bitmap.height());
1297f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        tmpISrc.intersect(*src);
1298f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        src = &tmpISrc;
1299f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1300f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    this->internalDrawBitmap(*bitmapPtr, src, matrix, paint);
13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPaint* paint) {
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
1306f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1309f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
1310f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com                                const SkMatrix& matrix, const SkPaint& paint) {
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
13129b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
13149b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1316f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint);
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13189b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
13254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (reject_bitmap(bitmap)) {
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
13364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(),
13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                 *paint);
13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength,
13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkScalar x, SkScalar y, const SkPaint& paint) {
13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawText(iter, text, byteLength, x, y, paint);
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength,
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           const SkPoint pos[], const SkPaint& paint) {
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
13584b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  paint);
13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength,
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkScalar xpos[], SkScalar constY,
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
13714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  paint);
13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPath& path, const SkMatrix* matrix,
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     matrix, paint);
13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPoint verts[], const SkPoint texs[],
13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkColor colors[], SkXfermode* xmode,
13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint16_t indices[], int indexCount,
13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
13994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                   colors, xmode, indices, indexCount, paint);
14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14044b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ITER_END
14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1408cb60844b34766aad4151df5e87c144d4a57e9abereed@android.comvoid SkCanvas::drawData(const void* data, size_t length) {
1409cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com    // do nothing. Subclasses may do something with the data
1410cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com}
1411cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com
14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1418845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
1422845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
14230baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1428845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
1432845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
14330baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
14404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
14484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
14574b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
14804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect storage;
14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (this->quickReject(paint.computeFastBounds(r, &storage),
14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              paint2EdgeType(&paint))) {
14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath  path;
14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path.addOval(r);
14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPath(path, paint);
14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (this->quickReject(paint.computeFastBounds(r, &storage),
15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  paint2EdgeType(&paint))) {
15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
15148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect storage;
15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (this->quickReject(paint.computeFastBounds(oval, &storage),
15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              paint2EdgeType(&paint))) {
15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
15208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath  path;
15238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path.addOval(oval);
15248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPath(path, paint);
15258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
15318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
15328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
15398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
15408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
15418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
15428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
15468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
15494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
15508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1554f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
1555f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com
15568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) {
15578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = save();
15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    picture.draw(this);
15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    restoreToCount(saveCount);
15608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1562f76bacff7f66724072c67edb185abf9e3add11a0reed@android.comvoid SkCanvas::drawShape(SkShape* shape) {
1563f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com    // shape baseclass takes care of save/restore
1564f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com    shape->draw(this);
1565f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com}
1566f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com
15678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
15688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
1571d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
15728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
15748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
15818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::LayerIter::device() const {
15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
15938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1607