SkCanvas.cpp revision d954498c01ccf0417feacf89e45d0c62a06a813b
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
89f0147143fbedba10bdae496d812a14995304924reed
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
10d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
129c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
1674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
1745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
18b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
200017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
257ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
2652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
27a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
31644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
32644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
33644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
34da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
35da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
3615e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
602c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
612c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
6297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
6397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
64c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
6597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
6697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
6797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
701f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
791f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
80045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix*     fMatrix;
826f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas,
85d954498c01ccf0417feacf89e45d0c62a06a813breed             bool conservativeRasterClip)
86d954498c01ccf0417feacf89e45d0c62a06a813breed        : fNext(NULL)
87d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
88d954498c01ccf0417feacf89e45d0c62a06a813breed    {
89d954498c01ccf0417feacf89e45d0c62a06a813breed        if (NULL != device) {
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
9140a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
9588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
9849f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
9940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
10388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1044b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1076f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1086f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
124045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1274b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1333fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1343fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
142f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
143f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1450e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com    SkMatrix    fMatrixStorage;
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1576f09709519b79a1159f3826645f1c5fbc101ee11reed    SkRasterClip    fRasterClip;
158d954498c01ccf0417feacf89e45d0c62a06a813breed    SkMatrix        fMatrix;
1591f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
160d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
16788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    DeviceCM*   fTopLayer;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
169d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
170d954498c01ccf0417feacf89e45d0c62a06a813breed        fMatrix.reset();
171d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter     = NULL;
172d954498c01ccf0417feacf89e45d0c62a06a813breed        fLayer      = NULL;
173d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer   = NULL;
174d954498c01ccf0417feacf89e45d0c62a06a813breed
175d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
176d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
177d954498c01ccf0417feacf89e45d0c62a06a813breed    }
178d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) {
179d954498c01ccf0417feacf89e45d0c62a06a813breed        fMatrix = prev.fMatrix;
180d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
182d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
183d954498c01ccf0417feacf89e45d0c62a06a813breed
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
18882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1968a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
1974370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
1988a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        fClipStack = &canvas->fClipStack;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2038a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
214f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
215f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
223f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
227199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2331f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
2346f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
2356f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
2396f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
25478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
25578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
2564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
2584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
2594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
2608926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        fDoClearImageFilter = false;
2614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2638926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
2648926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
2658926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            tmp.setImageFilter(fOrigPaint.getImageFilter());
266e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
267e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                            true, SkCanvas::kFullLayer_SaveLayerStrategy);
2688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // we'll clear the imageFilter for the actual draws in next(), so
2698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // it will only be applied during the restore().
2708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fDoClearImageFilter = true;
2718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
2728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
27379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
27479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
27579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
27679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
277129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
278129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
27979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
280129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
281129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = !fFilter && !fDoClearImageFilter;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
2854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
2868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (fDoClearImageFilter) {
2878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
2888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
2894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
29174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
2924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
2934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
2944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
2954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
29674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
297129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
298129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
299129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
300129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
301129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
302129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fPaint = &fOrigPaint;
303129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
304129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
305129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
306129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
307fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
30874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3102c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazyPaint;
3112c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
3122c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
3132c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
3142c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
3152c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
3168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    bool            fDoClearImageFilter;
3172c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
318129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
31979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
32079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
321129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
322129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
325129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
326632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
327129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
32879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
329632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
330129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkPaint* paint = fLazyPaint.set(fOrigPaint);
3318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
332129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fDoClearImageFilter) {
333129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
334129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
3358926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
33679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
337129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
338129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
339129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
340129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
341971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
342971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
343971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
344971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
34579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
346129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
347632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
348632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
349129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
350129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
3518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
352129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
35379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
3544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
3554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
3564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
357632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
358632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
3594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
3604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
3614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
3624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
3634e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
3644e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
37097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
3718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper  looper(this, paint, true);                      \
3728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
3738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
3748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
37578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
37697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
37778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    AutoDrawLooper  looper(this, paint, false, bounds);             \
3784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
3804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
385d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
386d954498c01ccf0417feacf89e45d0c62a06a813breed    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
387c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
388c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
3898f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
39045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
391f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
392b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount = 0;
393210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    fCullCount = 0;
39474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
396d954498c01ccf0417feacf89e45d0c62a06a813breed    if (device && device->forceConservativeRasterClip()) {
397d954498c01ccf0417feacf89e45d0c62a06a813breed        fConservativeRasterClip = true;
398d954498c01ccf0417feacf89e45d0c62a06a813breed    }
399d954498c01ccf0417feacf89e45d0c62a06a813breed
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
401d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
403d954498c01ccf0417feacf89e45d0c62a06a813breed    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip));
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
407f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
408f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
409f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
410f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
411f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->height()));
412f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
413f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
416cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
417e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
418e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
4198d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
420ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
421d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(NULL, kDefault_InitFlags);
4228d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
4238d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
424d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
425d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
426d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
427d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
428d954498c01ccf0417feacf89e45d0c62a06a813breed}
429d954498c01ccf0417feacf89e45d0c62a06a813breed
430d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
431d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
432d954498c01ccf0417feacf89e45d0c62a06a813breed    SkNoPixelsBitmapDevice(int width, int height) : INHERITED(make_nopixels(width, height)) {}
433d954498c01ccf0417feacf89e45d0c62a06a813breed
434d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
435d954498c01ccf0417feacf89e45d0c62a06a813breed
436d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
437d954498c01ccf0417feacf89e45d0c62a06a813breed};
438d954498c01ccf0417feacf89e45d0c62a06a813breed
439e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.orgSkCanvas::SkCanvas(int width, int height)
440e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
441e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
442e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
443d954498c01ccf0417feacf89e45d0c62a06a813breed
444d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_InitFlags)->unref();
445d954498c01ccf0417feacf89e45d0c62a06a813breed}
446e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
447d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(int width, int height, InitFlags flags)
448d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
449d954498c01ccf0417feacf89e45d0c62a06a813breed{
450d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
451d954498c01ccf0417feacf89e45d0c62a06a813breed
452d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unref();
45327a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
455d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
45627a5e656c3d6ef22f9cb34de18e1b960da3aa241reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
45727a5e656c3d6ef22f9cb34de18e1b960da3aa241reed{
45827a5e656c3d6ef22f9cb34de18e1b960da3aa241reed    inc_canvas();
459d954498c01ccf0417feacf89e45d0c62a06a813breed
460d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, flags);
461d954498c01ccf0417feacf89e45d0c62a06a813breed}
4626f09709519b79a1159f3826645f1c5fbc101ee11reed
463d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
464d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
465d954498c01ccf0417feacf89e45d0c62a06a813breed{
466d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
467d954498c01ccf0417feacf89e45d0c62a06a813breed
468d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap)
472e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
473e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
476d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)), kDefault_InitFlags)->unref();
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
482b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    SkASSERT(0 == fSaveLayerCount);
4837c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
487b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
50174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
50274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
50374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
50474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
50574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
50674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
50774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
50874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
511bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
5121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
513bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
514bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
515bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
516bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
517bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
5184ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
5194ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5204ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
5214ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5224ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5234ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
5244ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5254ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
5264ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5274ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5284ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
5291f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
530210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
531210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
532210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
5331f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
535c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5401f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
5410b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
5420b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
5430b53d59a24f667350b4282f88470713902409030reed@google.com    }
5449266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
5459266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
5469266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
547403f8d7a052269583175e945689824838e5e0ef4commit-bot@chromium.orgSkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
5494c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
5504c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5521f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice == device) {
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return device;
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5574b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (device) {
55940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        device->onAttachToCanvas(this);
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice) {
56240a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        rootDevice->onDetachFromCanvas();
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rootDevice = device;
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
5694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Now we update our initial region to have the bounds of the new device,
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and then intersect all of the clips in our stack with these bounds,
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to ensure that we can't draw outside of the device's bounds (and trash
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                     memory).
5744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this is only a partial-fix, since if the new device is larger than
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the previous one, we don't know how to "enlarge" the clips in our stack,
5774b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        so drawing may be artificially restricted. Without keeping a history of
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reconstruct the correct clips, so this approximation will have to do.
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The caller really needs to restore() back to the base if they want to
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        accurately take advantage of the new device bounds.
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58442aea289cbf801997b653a906a37a7f7e948b645reed@google.com    SkIRect bounds;
58542aea289cbf801997b653a906a37a7f7e948b645reed@google.com    if (device) {
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds.set(0, 0, device->width(), device->height());
58742aea289cbf801997b653a906a37a7f7e948b645reed@google.com    } else {
58842aea289cbf801997b653a906a37a7f7e948b645reed@google.com        bounds.setEmpty();
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
59042aea289cbf801997b653a906a37a7f7e948b645reed@google.com    // now jam our 1st clip to be bounds, and intersect the rest with that
5911f836ee096bb988adef4b9757b2629c7afeda36dreed    rec->fRasterClip.setRect(bounds);
59242aea289cbf801997b653a906a37a7f7e948b645reed@google.com    while ((rec = (MCRec*)iter.next()) != NULL) {
5931f836ee096bb988adef4b9757b2629c7afeda36dreed        (void)rec->fRasterClip.op(bounds, SkRegion::kIntersect_Op);
59442aea289cbf801997b653a906a37a7f7e948b645reed@google.com    }
59542aea289cbf801997b653a906a37a7f7e948b645reed@google.com
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
599a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
600a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
601a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
602a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
603a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
604a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
605a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
606848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
607a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
608a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
609a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
610a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
611a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
612a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBitmap bm(*bitmap);
613a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bm.lockPixels();
614a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
615a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return true;
616a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
617a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
618a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
619a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
620a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
621a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
622a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
62351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
624c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
625a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
626a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
627a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
628a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
629ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
630ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
63174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
632848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
633a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
634a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
635a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
636a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
637a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
638daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
639c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
640a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
641a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
642c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
643a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
644a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    switch (origInfo.colorType()) {
645a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kUnknown_SkColorType:
646a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kIndex_8_SkColorType:
647a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
648a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        default:
649a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            break;
650a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
651a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
652a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
653a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
654a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (0 == origInfo.width() || 0 == origInfo.height()) {
65551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
65651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
657a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
658a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
659a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
660a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
661a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
662a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
663a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
664a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
665a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!srcR.intersect(0, 0, size.width(), size.height())) {
666a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
667a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
668db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
669a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // the intersect may have shrunk info's logical size
670e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(srcR.width(), srcR.height());
671db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
672a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
673a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (x > 0) {
674a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        x = 0;
675a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
676a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (y > 0) {
677a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        y = 0;
678a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
679a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // here x,y are either 0 or negative
680a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
681db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
682a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
683a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
68451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
68551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
6864cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
6874cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
6884cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
6894cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
6904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bm(bitmap);
6914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    bm.lockPixels();
6924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bm.getPixels()) {
6934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
6944cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
6954cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
6964cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
6974cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
6984cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
6994cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
7004cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
7014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
7024cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
7034cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
7044cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
7054cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
7064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
7084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
7124cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
7134cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
7144cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7164cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7174cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
7184cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
7194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7224cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
723e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
7244cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7254cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
7264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
7274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
7284cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
7304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
7314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
7334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
7344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7354af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
7364af35f348b2e2f6c428819118eb7a2f2fff53a74reed    this->predrawNotify();
7374af35f348b2e2f6c428819118eb7a2f2fff53a74reed
7384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
7394ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
7404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
74151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
7434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
7444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7454370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
7511f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
7534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
75546799cd9f0bded51a189d77731b25af159ab4609reed@google.com            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
75946799cd9f0bded51a189d77731b25af159ab4609reed@google.com                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7685f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitaint SkCanvas::internalSave() {
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = this->getSaveCount(); // record this before the actual save
7704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
772d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
7744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7755f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    fClipStack.save();
7765c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return saveCount;
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
780d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::save() {
7815f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->willSave();
7825f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    return this->internalSave();
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
786b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
788b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
789b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
790b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
793a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
794c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                               SkIRect* intersection, const SkImageFilter* imageFilter) {
795bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
796c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkRegion::Op op = SkRegion::kIntersect_Op;
797bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
798a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
799f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
800c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
801c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
8021f836ee096bb988adef4b9757b2629c7afeda36dreed        imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds);
803c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        // Filters may grow the bounds beyond the device bounds.
804c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        op = SkRegion::kReplace_Op;
805c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
806bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
80749f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
8094b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->getTotalMatrix().mapRect(&r, *bounds);
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
814bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
8151f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
816bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
817a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
82389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
82489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        fClipStack.clipDevRect(ir, op);
82589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        // early exit if the clip is now empty
8261f836ee096bb988adef4b9757b2629c7afeda36dreed        if (!fMCRec->fRasterClip.op(ir, op)) {
82789f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org            return false;
82889f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        }
829a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
830a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
831a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
832a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
833a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
834a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
835a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
836a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
837d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
838d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
839d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
840d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
841d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
842a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
843a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org                        SaveFlags flags) {
844e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
845e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, flags, false, strategy);
8468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
8478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
848e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
849e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                bool justForImageFilter, SaveLayerStrategy strategy) {
850b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
8512a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
852b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
853b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
854a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
855a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
8565f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    int count = this->internalSave();
857a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
858a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
859a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
860a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
861c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return count;
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
865e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
866e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
867e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
868e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        return count;
869e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
870e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
871b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    // Kill the imagefilter if our device doesn't allow it
872b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    SkLazyPaint lazyP;
873b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    if (paint && paint->getImageFilter()) {
874b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
8758926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            if (justForImageFilter) {
8768926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                // early exit if the layer was just for the imageFilter
8778926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                return count;
8788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
879b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            SkPaint* p = lazyP.set(*paint);
880b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            p->setImageFilter(NULL);
881b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            paint = p;
882b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
883b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
884b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com
88515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
88615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
88715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8891f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device;
89076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    if (paint && paint->getImageFilter()) {
89152d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed        device = this->getDevice();
89252d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed        if (device) {
89352d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed            device = device->createCompatibleDevice(info);
89452d9ac6c92ddf33b3b05eb77ba9509a7aa441657reed        }
89576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    } else {
89615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        device = this->createLayerDevice(info);
89776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    }
898e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    if (NULL == device) {
899e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        SkDebugf("Unable to create device for layer.");
900e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        return count;
901e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
902e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
9036f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
904d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM* layer = SkNEW_ARGS(DeviceCM,
905d954498c01ccf0417feacf89e45d0c62a06a813breed                                 (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip));
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
912b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount += 1;
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
916d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
917d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
918d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
919d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() {
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check for underflow
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCStack.count() > 1) {
934e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        this->willRestore();
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->internalRestore();
9366cfa73a29a26edf1d03bca224ad6860396308ffcmtklein        this->didRestore();
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
944c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9465f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    fClipStack.restore();
9476c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
94888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
96249f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
9646f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
9658926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
9668926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                     layer->fPaint);
9678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
9697c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
970b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            SkASSERT(fSaveLayerCount > 0);
971b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            fSaveLayerCount -= 1;
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(layer);
97488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const {
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCStack.count();
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) {
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // sanity check
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count < 1) {
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 1;
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
98674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
987b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    int n = this->getSaveCount() - count;
988b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    for (int i = 0; i < n; ++i) {
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->restore();
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9937c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const {
994b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    return fSaveLayerCount > 0;
9957c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com}
9967c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
99776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
99876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return this->onNewSurface(info);
99976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
100076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
100176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
100276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
100376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return dev ? dev->newSurface(info) : NULL;
100476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
100576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1006c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1007c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1008c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1009c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1010c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1011900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1012c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1013c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1014c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1015c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1016c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return this->onPeekPixels(info, rowBytes);
1017c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1018c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1019c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1020c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1021c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1022c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1023c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
10246b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
10256b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
10266b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    if (pixels && origin) {
10276b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
10286b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
10296b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    return pixels;
10309c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
10319c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
10329c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comvoid* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
10339c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
10349c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessPixels(info, rowBytes) : NULL;
10359c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
10369c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1037c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1038c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1039c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1040c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1041848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1042c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1043c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1044c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1045c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1046c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1047c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1048c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1049c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1050c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1051c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1052c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1053c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1054c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
105500f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1056c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1057c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1058c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1059c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1060c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1061c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1062210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPushCull(const SkRect& cullRect) {
1063210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1064210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1065210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
1066210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPopCull() {
1067210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1068210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1069210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
1071520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1072520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org// Ensure that cull rects are monotonically nested in device space.
1073520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::validateCull(const SkIRect& devCull) {
1074520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullStack.isEmpty()
1075520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || devCull.isEmpty()
1076520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || fCullStack.top().contains(devCull)) {
1077520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        return;
1078520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1079520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1080520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1081520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1082520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().x(), fCullStack.top().y(),
1083520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().right(), fCullStack.top().bottom()));
1084520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1085520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef ASSERT_NESTED_CULLING
1086520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGFAIL("Invalid cull.");
1087520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1088520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1089520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1090520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1091520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::pushCull(const SkRect& cullRect) {
1092520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    ++fCullCount;
1093520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->onPushCull(cullRect);
1094520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1095520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1096520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Map the cull rect into device space.
1097520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkRect mappedCull;
1098520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1099520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1100520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Take clipping into account.
1101520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkIRect devClip, devCull;
1102520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    mappedCull.roundOut(&devCull);
1103520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getClipDeviceBounds(&devClip);
1104520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (!devCull.intersect(devClip)) {
1105520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        devCull.setEmpty();
1106520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1107520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1108520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->validateCull(devCull);
1109520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    fCullStack.push(devCull); // balanced in popCull
1110520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1111520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1112520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1113520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::popCull() {
1114520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkASSERT(fCullStack.count() == fCullCount);
1115520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1116520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullCount > 0) {
1117520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        --fCullCount;
1118520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        this->onPopCull();
1119520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1120520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        SkDEBUGCODE(fCullStack.pop());
1121520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1122520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1123520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1124520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11269bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
112850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11322c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
11342c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11369bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11379bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
11389bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
113978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
114078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
114178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
114278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
114378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
114478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
114578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
114678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
114778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
11489bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11499bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
11509bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
11519bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
11529bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11539bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11561f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
11578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                  const SkPaint* paint) {
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp.setDither(true);
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11648926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
11661f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
116776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
116876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
116976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
11708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
11719c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(dstDev);
117276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
11736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1174b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1175fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1176d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
11774cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1178be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
117955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
11804cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
11815efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
11825efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
11836776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
11846776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
118576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
118676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1187b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
118876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
11948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                          const SkPaint* paint) {
119550b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
11968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
11978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
119850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1199fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
12018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
12028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
12038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1204fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12058926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1206fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12078926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
12088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
12098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
12108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
12129c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(iter.fDevice);
12138926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
12146776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1215fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1216d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12174cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1218be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
121955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
12204cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
12215efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12225efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12245efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
12258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
12268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
12278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
12288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
12298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
12308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
12318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
12328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
123492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1235d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1236d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1237d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
124092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1241d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1242d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1243d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
124692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1247d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1248d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1249d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
125292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1253d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1254d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1255d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
125644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
125744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
125892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1259d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1260d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1261d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1262d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1264c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
12651f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
126644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
126744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
126844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
126944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1272c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
12731f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
127444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
12794b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1286759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
12878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
12888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
12898f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
12908f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
12918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1292da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1293da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
12941f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1295da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1296da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1297da17f758442f16747af39f8fbaed9c097048519creed@google.com
12983b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1299da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1300c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1301da17f758442f16747af39f8fbaed9c097048519creed@google.com
1302da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
13031f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1304da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1305da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1306da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1307da17f758442f16747af39f8fbaed9c097048519creed@google.com
13085c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
13095c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1311c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13128f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
13138f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
13148f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13161f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1317123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
131898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
131998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
132098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13231f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
13248f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1325d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1327123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
132898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
132998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
133098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
13348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133873e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
133973e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1340d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1341819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1342819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1343759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
13448f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13454ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
13468f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
13478f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
13488f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
13494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
13508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
135114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
13528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
135314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
13541f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
135514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
135614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
135714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
135814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
13598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
13608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
13618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
136214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
13638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
136414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
136514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
136614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
136714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
136873e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
13698f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
137014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
137114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
137214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
137314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
137414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
13758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
13764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
13774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1378759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
13798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
13818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
13828f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
13838f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
13848f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
13858f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
13868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
13878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
13888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1389da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1390da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
13911f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1392da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1393da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1394fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13953b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1396da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1397c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1398fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1399da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
14001f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1401da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1402da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1403da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1404da17f758442f16747af39f8fbaed9c097048519creed@google.com
14055c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14065c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1408c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14098f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14108f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14118f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
14141f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1416fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1417fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1418fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1419fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1420fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1421fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1422fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1423fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1424fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1425fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
14265c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
14278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
14285c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
142945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
143045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.reset();
143145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
143245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack* clipStack = getClipStack();
143345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
143445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack::Element* element;
143545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        while ((element = iter.next())) {
143645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkClipStack::Element::Type type = element->getType();
143745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkPath operand;
14382a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org            if (type != SkClipStack::Element::kEmpty_Type) {
14392a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org                element->asPath(&operand);
14402a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org            }
144145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkRegion::Op elementOp = element->getOp();
144245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (elementOp == SkRegion::kReplace_Op) {
144345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                devPath = operand;
144445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else {
144545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
144645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
144796fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
144896fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // perhaps we need an API change to avoid this sort of mixed-signals about
144996fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // clipping.
14508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            if (element->isAA()) {
14518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                edgeStyle = kSoft_ClipEdgeStyle;
14528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            }
145345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
145445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
145545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
145645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
145773e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1460759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
14618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
14628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
14655c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14665c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1468c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14705c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
14715c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1472115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com    fClipStack.clipDevRect(rgn.getBounds(), op);
14735c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14741f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1477819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1478819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1479819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
14801f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1481ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
14825c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1483ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1484ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1485ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1486819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1487819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1488d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1489819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
149080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
14918182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
14928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
14938182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
14948182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
14958182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
14968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
14978182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
14988182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
14998182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
15008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15019cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
15029cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
15039cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
150473e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
15059cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
15069cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1507819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1508819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1509819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1510819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1511819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
151290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
151380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
15148182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
15158182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
15168182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1517c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
151890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
151990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
152090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15215c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15225c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1523754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
15241f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1525754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1526754de5f65b466f721d952a379194cc94de376f42reed@google.com
15275c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
15281f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
15295c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
15305c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
15313b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
15321607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1533116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1534116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
15351f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15391f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1540a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
15411f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1542a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkIRect idst;
1543a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        dst.roundOut(&idst);
15441f836ee096bb988adef4b9757b2629c7afeda36dreed        return !SkIRect::Intersects(idst, fMCRec->fRasterClip.getBounds());
1545a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1546c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1547d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1548a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1549c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1550c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1551a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1552a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1553c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1554a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1555a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1556a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
15578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15603b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
15613b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
15628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15643b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1565bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
15668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
15678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
15688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1570d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1571d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
15721f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
157372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
157472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
157572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1576d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1577d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1578d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
157949f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1580bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
15813b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
15823b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1583fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
15848f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
15858f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
15868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1591bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
15921f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1593bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1594bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1595bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1596bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1597bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1598bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1599bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
160049f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1601bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1602bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1603bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1604bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1605bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16071f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16105c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
16111f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
16125c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16135c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16149c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
16159c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16169c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
16179c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16189c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
161915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
16201f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getTopDevice();
162115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1624644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1625644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1626644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
162749f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1628644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
162949f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1630644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1631644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1632644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1633644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1634644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1635644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1636644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1637644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1638e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1639ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1640ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
1641ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1642ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1643ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1644ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1645ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1646ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1647ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1648ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1649ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1650ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1651ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1652ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1653ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1654ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1655ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1656ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1657ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1658ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16632a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) {
16642a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    SkDrawIter  iter(this);
1665995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org    this->predrawNotify();
16662a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    while (iter.next()) {
16672a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com        iter.fDevice->clear(color);
16682a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    }
16692a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com}
16702a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com
167128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
167249f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
167328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
167428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
167528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
167628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) {
1678fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1679fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1680fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1681fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
168278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
16854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
169778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
169878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1699a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1700a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1701a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1702a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1703a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1704a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1705a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
170678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
170778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1708a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1709a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1710fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1711a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
171478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
17154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
17204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17237ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
172478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
172578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
172778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(r, &storage);
172878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
173378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
17378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
174378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
174478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17454ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
174678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
174778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17484ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
17494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
17504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1751306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
175278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
175346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
175446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
175546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
175646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
175746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
175846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
17594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
17604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
17614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
176278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
176378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17644ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
176578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
176678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17674ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
17684ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
17694ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
17704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
17714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
17724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
17734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1774f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
1775f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
17764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
1777f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1778f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
17794ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1780f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
178178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1782f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1783f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
1784f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1785f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1786f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1787f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
17884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
17894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1790ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1791ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
1792ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
1793ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
1794ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
1795ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1796ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
1797ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
1798ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
1799ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
180025c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1801ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
180225c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1803ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
1804ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1805ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
180625c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1807ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
1808ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
18094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
18107ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
18119364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
18129364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
18139364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
18149364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
181578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
181678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1817fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
181878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
181978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
182078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18240b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
18250b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
18260b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
18276803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
1828fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
1829fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
1830fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
1831fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
183378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18463d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
18479efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
18489efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
18499efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
18509efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
18519efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
18529efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
18539efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
18549efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
18553b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
18629bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18659987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
18667112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1867eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
1868eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
186950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
187274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
187378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
187478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
18753d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
18769efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
18779efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
18789efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
18793b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
18803d60812865bb034851da777a91413ab584929887reed@google.com            return;
18813d60812865bb034851da777a91413ab584929887reed@google.com        }
18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18833d60812865bb034851da777a91413ab584929887reed@google.com
188433535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
188533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
188633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18887064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
188978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
18907064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
189133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
1892eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1893f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
18947064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
189533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18987112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1899eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    const SkRect& dst, const SkPaint* paint,
1900eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    DrawBitmapRectFlags flags) {
19019987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
1902eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
19039987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
19049987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
19068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPaint* paint) {
19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
19089bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
19098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19119987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
19129987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
19139987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
191450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
191550b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
191650b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
19173d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
191860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
191960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
192060abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
192160abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
192260abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
19233b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
19243d60812865bb034851da777a91413ab584929887reed@google.com            return;
19253d60812865bb034851da777a91413ab584929887reed@google.com        }
19263d60812865bb034851da777a91413ab584929887reed@google.com    }
19273d60812865bb034851da777a91413ab584929887reed@google.com
19289987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
19299987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
19309987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19319987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
19329987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
19339987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
19349987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
19359987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
19369987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
19379987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19387112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
19397d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
19407112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
19417112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
19427d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
19437112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
19449987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
19459987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
19469987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
19479987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
19489987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
19499987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
19509987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
19519987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
195274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
19539987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
19549987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
19559987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
19569987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
195774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
19589987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
19599987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
19609987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
19619987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
196274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
19639987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
19647112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
19657112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
19669987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
19679987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
19689987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
19699987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
19709987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
19719987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
19729987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
19739987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
19749987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
1975eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
197631acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
19779987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
19789987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
19799987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
19809987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19819987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
19829987ec3791336bad6af5cbe513564786b2df55aareed@google.com                              const SkRect& dst, const SkPaint* paint) {
19839987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
19849987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19859987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
19869987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
19879987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
19889987ec3791336bad6af5cbe513564786b2df55aareed@google.com
1989f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
1990f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
19911f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
19921f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice::TextFlags flags;
1993f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        if (device->filterTextFlags(paint, &flags)) {
1994a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
1995f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setFlags(flags.fFlags);
1996f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setHinting(flags.fHinting);
1997f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
1998f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
1999f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2000f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2001f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2002f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2003f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2004f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2005f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
20062c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
20072c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2008f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2009f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
201052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
201152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
201217b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
201352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
201452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
201552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
201617b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
201752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
201852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
201952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
202052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
202152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
202252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
202352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
202452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
202552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
202652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
202752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
202852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
202952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
203052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
203152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
203252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
203352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
203452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
203552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
203652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
203752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
203852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
203952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
204052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
204152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
204252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
204352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
204452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
204552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
204652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
204752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
204852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
204952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
205052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
205152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
205252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
205352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
205452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
205552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
205652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
205752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
205852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
205952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
206052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
206152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
206252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
206352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
206452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
206552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
206652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
206752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
206852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
206952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
207052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
207152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
207252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
207352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
207452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
207552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
207652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
207752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
207852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
207952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
208052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
208152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2082e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2083e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
208478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2088f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
208952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
209052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
20918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2096e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2097e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
209878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
209987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
21028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2103f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2105b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
21064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2109e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2110e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
211178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
211287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2116f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2118b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
21194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2122e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2123e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
212478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
212587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
21284e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2130b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2131945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
21324325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
21334325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
213400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
213500d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
21367ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
21377ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    // FIXME: temporarily disable quickreject for empty bounds,
21387ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    // pending implicit blob bounds implementation.
21397ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    if (!blob->bounds().isEmpty() && paint.canComputeFastBounds()) {
21407ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        SkRect storage;
21417ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
21427ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
21437ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita            return;
21447ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        }
21457ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
21467ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2147aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
214800d5c2c6523321d25b32905ff4822f083a4173eefmalita
2149aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2150aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2151aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
215200d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
215300d5c2c6523321d25b32905ff4822f083a4173eefmalita
2154aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
215500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
215600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2157e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2158e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2159e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
2160e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2161e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2162e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2163e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
2164e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2165e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2166e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2167e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
2168e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2169e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2170e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2171e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
2172e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2173e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
217400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
217500d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
217649f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
217700d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
217800d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
217900d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2180e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPoint verts[], const SkPoint texs[],
21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkColor colors[], SkXfermode* xmode,
21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint16_t indices[], int indexCount,
21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
218678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
21874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
21904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
21914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2197b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2198b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2199b3c9d1c33caf325aada244204215eb790c228c12dandov    if (NULL == cubics) {
2200b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2201b3c9d1c33caf325aada244204215eb790c228c12dandov    }
22026cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2203ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2204ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2205ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2206b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2207ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2208ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2209ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
22106cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2211b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2212b3c9d1c33caf325aada244204215eb790c228c12dandov}
2213b3c9d1c33caf325aada244204215eb790c228c12dandov
2214b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2215b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2216b3c9d1c33caf325aada244204215eb790c228c12dandov
2217ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
22186cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2219ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2220b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2221ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
22226cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2223ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2224ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2225ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
22298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2232845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2236845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
22370baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2242845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
22438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
22448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2246845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
22470baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
22488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
22544b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
22568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
22578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
22624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
22648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
22658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
22708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
22714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
22838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
22878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
22888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
22898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
22908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
22938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
22944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
22958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
22988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
23008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
23018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
23023b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
23064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
23074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
23084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
23098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
23158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
23168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
23178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
23208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
23218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
23228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
23238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
23258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
23268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
23278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
23288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
23338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
23358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
23364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
23388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2341f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
23429b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
2343145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
234449f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2345145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        device->EXPERIMENTAL_optimize(picture);
2346145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2347145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org}
2348f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com
23499b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::drawPicture(const SkPicture* picture) {
235049f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2351d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->onDrawPicture(picture, NULL, NULL);
23529b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    }
23539b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips}
23549b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2355d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
235649f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2357d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
2358d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            matrix = NULL;
2359d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2360d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->onDrawPicture(picture, matrix, paint);
2361d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2362d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
23639b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2364d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2365d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2366145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
236749f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2368145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2369145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2370d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2371145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2372145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2373145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2374145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2375a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2376d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2377c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
23788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
23818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
23828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2384d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
23858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
23878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
23898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
23908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
23938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
23948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
23978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
23988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24001f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
24028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
24068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
24098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
24108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
24118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
24148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
24178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
24188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
241920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
242020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
242120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2422c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
24233107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24243107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
24253107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24263107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
24273107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
24283107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
24293107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
24303107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
24313107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
24323107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
24333107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
24343107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24353107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
24363107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
24373107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
243828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
24393107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
24403107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
24413107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
24423107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
24433107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24443107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
24453107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
24463107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24473107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgSkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
24483107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
24493107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
24503107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
24513107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24523107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkBitmap bitmap;
2453848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap.tryAllocPixels(info)) {
24543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
24553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
24563107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
24573107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    // should this functionality be moved into allocPixels()?
24583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!bitmap.info().isOpaque()) {
24593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        bitmap.eraseColor(0);
24603107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
24613107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
24623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
246342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org
246442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
246542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
246642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
246742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2468eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
246942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
247042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
247142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
247242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
247342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
247442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2475d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2476d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2477d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2478d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2479a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2480d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2481d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2482d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
248349f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2484a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2485d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2486a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2487d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2488a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
248949f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2490d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2491d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
24926cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
249349f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2494d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2495d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2496d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2497d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2498d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2499d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2500d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2501