SkCanvas.cpp revision e47829b6b1eeb6b0c97ccb3df3016d197046824c
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
8d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkBitmapDevice.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
10d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
11d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
12dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
13d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkDevice.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
153cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
185f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkErrorInternals.h"
19b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
2074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
214c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkNinePatchIter.h"
22c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
23b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
250017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
2696472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
274ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
307ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
32a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
338f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
34d3ebb48320cf1b7e969974673e4bd7743816985ebungeman
35d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
38644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
39644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
40644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
41c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
42c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
43c83a29759a5c2966da5ab973e4fd90763e4c962breed *
44c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
45c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
46c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
47c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
48c83a29759a5c2966da5ab973e4fd90763e4c962breed */
49c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
50c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
51c83a29759a5c2966da5ab973e4fd90763e4c962breed    SK_COMPILE_ASSERT((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
52c83a29759a5c2966da5ab973e4fd90763e4c962breed                      (int)kNone_ShaderOverrideOpacity,
53c83a29759a5c2966da5ab973e4fd90763e4c962breed                      need_matching_enums0);
54c83a29759a5c2966da5ab973e4fd90763e4c962breed    SK_COMPILE_ASSERT((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
55c83a29759a5c2966da5ab973e4fd90763e4c962breed                      (int)kOpaque_ShaderOverrideOpacity,
56c83a29759a5c2966da5ab973e4fd90763e4c962breed                      need_matching_enums1);
57c83a29759a5c2966da5ab973e4fd90763e4c962breed    SK_COMPILE_ASSERT((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
58c83a29759a5c2966da5ab973e4fd90763e4c962breed                      (int)kNotOpaque_ShaderOverrideOpacity,
59c83a29759a5c2966da5ab973e4fd90763e4c962breed                      need_matching_enums2);
60c83a29759a5c2966da5ab973e4fd90763e4c962breed
61c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
62c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
63c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (!this->getClipStack()->quickContains(bounds)) {
64c83a29759a5c2966da5ab973e4fd90763e4c962breed        return false;
65c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
66c83a29759a5c2966da5ab973e4fd90763e4c962breed
67c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
68c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!this->getTotalMatrix().rectStaysRect()) {
69c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
70c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
71c83a29759a5c2966da5ab973e4fd90763e4c962breed
72c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkRect devRect;
73c83a29759a5c2966da5ab973e4fd90763e4c962breed        this->getTotalMatrix().mapRect(&devRect, *rect);
748c0144ccb17220db9d5140ef5ee85d5bc7837513fmalita        if (!devRect.contains(bounds)) {
75c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
76c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
77c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
78c83a29759a5c2966da5ab973e4fd90763e4c962breed
79c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
80c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
81c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
82c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
83c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
84c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
85c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
86c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
87c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
88c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
89c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
90c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
91c83a29759a5c2966da5ab973e4fd90763e4c962breed}
92c83a29759a5c2966da5ab973e4fd90763e4c962breed
93c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
94c83a29759a5c2966da5ab973e4fd90763e4c962breed
95d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
96d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
97d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
98d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
99d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
100d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
101d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
102d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1030acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1040acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1050acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1060acf1b4b3645772d220c720313821bac389751b5reed}
1070acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1080acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1090acf1b4b3645772d220c720313821bac389751b5reed}
1100acf1b4b3645772d220c720313821bac389751b5reed
111da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
112da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
11315e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1372c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1382c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
139c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
14097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
141c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
142c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
143c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
144c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
145c83a29759a5c2966da5ab973e4fd90763e4c962breed}
146c83a29759a5c2966da5ab973e4fd90763e4c962breed
147c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
148c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
149c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
150c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
151c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
152c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
153c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
154c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
155c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
156c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
157c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
158c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
159c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
160c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
16197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
16297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
16397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1664a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
1674a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
1684a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
1694a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
1704a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1714a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
1724a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
1734a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1744a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
1754a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1764a8126e7f81384526629b1e21bf89b632ea13cd9reed
1774a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
1784a8126e7f81384526629b1e21bf89b632ea13cd9reed
1791f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1881f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1906f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
19161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
19261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
19361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const bool          fDeviceIsBitmapDevice;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19596e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
19686a17e7716c8db858e219a46b9db3817bb770beereed             bool conservativeRasterClip, bool deviceIsBitmapDevice)
197d954498c01ccf0417feacf89e45d0c62a06a813breed        : fNext(NULL)
198d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
19961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
200d954498c01ccf0417feacf89e45d0c62a06a813breed    {
201d954498c01ccf0417feacf89e45d0c62a06a813breed        if (NULL != device) {
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
20340a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
20788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
21049f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
21140a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
21488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
21588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
217feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
218feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
219feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
220feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
221feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
222feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
223feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
224045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
225045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
2266f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
2276f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
2304b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
2394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
243045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
2464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
248045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2523fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
2533fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
261f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2731f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
274d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
286d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
287d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter     = NULL;
288d954498c01ccf0417feacf89e45d0c62a06a813breed        fLayer      = NULL;
289d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer   = NULL;
2902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
292b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
293d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
294d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
295d954498c01ccf0417feacf89e45d0c62a06a813breed    }
2962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
297d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
299d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
3002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
301b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
30682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
310feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
311feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
312feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
313feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
314feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
315feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
316feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
317feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
318feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3238a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
3244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
3258a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
328687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
3308a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
341f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
342f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
345045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
346045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
34841e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
34941e010cb901c0da9066c4df562030808c9ccd7f8reed                fDst.reset(fDevice->imageInfo(), NULL, 0);
35041e010cb901c0da9066c4df562030808c9ccd7f8reed            }
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
352f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
356199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3614b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3621f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3636f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3646f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3686f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
380dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
381dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
382dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
383dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
384dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
385dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
386dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  colorfilter, else return NULL.
387dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
388dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkColorFilter* image_to_color_filter(const SkPaint& paint) {
389dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
390dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
391dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
392dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
393dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* imgCF;
395dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf->asAColorFilter(&imgCF)) {
396dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
397dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
398dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
400dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (NULL == paintCF) {
401dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
402dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
404dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
405dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
406dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
407dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
408dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
409dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
410dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
4134a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
41478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
41578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
4164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4184a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4205c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
423dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
424dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
425dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
426dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setColorFilter(simplifiedCF)->unref();
427dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setImageFilter(NULL);
428dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
429dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
430dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
431dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4325c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4335c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4345c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4355c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4365c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4375c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4385c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4395c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4405c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4415c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4425c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4435c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4445c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4455c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4465c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
448dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
449dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setXfermode(fPaint->getXfermode());
450e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
45176033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4525c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
4535c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
4548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
45679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
45779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
45879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
45979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
460129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
461129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
46279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
463129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
4645c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
466b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
4674a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
4684a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
4694a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
470dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
4714a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
4724a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
4734a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
4744a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
47674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
4785c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
4798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
4808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
48374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
4854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
4864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
4874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
48874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
489129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
490129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
491129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
492129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
493129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
494129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
495129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
496129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
497129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
498fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
49974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
501dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
502dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5032c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5042c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5052c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5062c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5072c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5084a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
5095c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5102c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
511129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
51279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
51379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
514129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
515129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
519632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
520129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5215c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
522632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
523dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
524dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5254a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
5268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5275c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
528129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
5295c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        paint->setXfermode(NULL);
530129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
53279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
533129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
534129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
535129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
536129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
537971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
538971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
539971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
540971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
54179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
542129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
543632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
544632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
545129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
546129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
548129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
54979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5514e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5524e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
553632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
554632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
5554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
5564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5574e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5638926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
56497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5654a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
5668926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
5678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
5688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
56978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
57097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5714a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
5724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
5744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
575c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
576c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
577c83a29759a5c2966da5ab973e4fd90763e4c962breed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
578c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
579c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
580c83a29759a5c2966da5ab973e4fd90763e4c962breed
5814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
585feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
586feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
587feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBounds.setEmpty();
588feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBoundsDirty = true;
589feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
590feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
591feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
592feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
593feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
594feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
595feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
596feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
597d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
598d954498c01ccf0417feacf89e45d0c62a06a813breed    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
599c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
600c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
6018f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
60245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
603f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
6042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
60574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
607687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack.reset(SkNEW(SkClipStack));
608687fa1c745febb57f42b0d5f03d7c1f4be2530careed
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
610d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
612a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
613a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
61486a17e7716c8db858e219a46b9db3817bb770beereed    new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false);
615b679ca8926a832274b14fdb512f88f64b61d32eareed
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
61897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
619f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
620f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
621efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
622efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
6234a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (device->forceConservativeRasterClip()) {
6244a8126e7f81384526629b1e21bf89b632ea13cd9reed            fConservativeRasterClip = true;
6254a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
626f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
627f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
62878e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
629f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
630f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
633cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
634e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6354a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
636e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6378d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
638ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
639d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(NULL, kDefault_InitFlags);
6408d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6418d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
642d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
643d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
644d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
645d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
646d954498c01ccf0417feacf89e45d0c62a06a813breed}
647d954498c01ccf0417feacf89e45d0c62a06a813breed
648d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
649d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
650fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
651fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
65278e276889795454891cbba48ab11927968114953reed    {
65378e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
65478e276889795454891cbba48ab11927968114953reed    }
655d954498c01ccf0417feacf89e45d0c62a06a813breed
656d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
657b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
658d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
659d954498c01ccf0417feacf89e45d0c62a06a813breed};
660d954498c01ccf0417feacf89e45d0c62a06a813breed
66196a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
662e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
66396a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
664e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
665e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
666b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
66778e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
668fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips                          (SkIRect::MakeWH(width, height), fProps)), kDefault_InitFlags)->unref();
669d954498c01ccf0417feacf89e45d0c62a06a813breed}
670e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
67178e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
672d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6734a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
674d954498c01ccf0417feacf89e45d0c62a06a813breed{
675d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
676b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
677fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds, fProps)), flags)->unref();
67827a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
680d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
681d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6827b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
683d954498c01ccf0417feacf89e45d0c62a06a813breed{
684d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
685b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
686d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
689fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
690fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6917b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
692fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
693fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
694fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
695fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
696fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
697fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
6984a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
6993716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7004a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
7013716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7023716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
703b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
704fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap, fProps)));
7054a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7064a8126e7f81384526629b1e21bf89b632ea13cd9reed}
70729c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
7084a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
7094a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7104a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
7114a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7124a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
713b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
714fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap, fProps)));
7154a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7217c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
725b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
73451985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
73974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
74074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
74174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
74274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
74374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
74474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
74574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
74674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
74774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
750bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
7511f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
752bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
753bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
754bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
755bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
756bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
7574ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
7584ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
7594ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
7604ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
7614ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
7624ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
7634ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
7644ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
7654ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
7664ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
7674ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
7681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
769210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
770210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
771210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
7721f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
774c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7791f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
7800b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
7810b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
7820b53d59a24f667350b4282f88470713902409030reed@google.com    }
7839266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
7849266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
7859266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
786a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
787a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
788a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
789a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
790a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
791a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
792a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
793848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
794a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
795a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
796a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
797a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
798a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
799cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
800cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
801cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
802cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
803cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
804cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
805a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
806a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
807a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
808a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
809a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
810a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
811a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
81251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
813c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
814a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
815a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
816a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
817a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
818ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
819ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
82074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
821848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
822a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
823a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
824a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
825a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
826a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
827daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
828c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
829a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
830a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
831c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
83296472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
833a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
834a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
835a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
836a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
837a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
838f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
83996472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
84096472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
841a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
842a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
843db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
844a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
84596472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
84651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
84751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
8494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
8504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
852cf01e31df6bbda270dca2ee3b4967caf51e465dcreed
853cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
854cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
855cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
856cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
8574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
8594cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
8604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
8624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
8634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
8644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
8654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
8664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
8674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
8684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
8694cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8704cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
8714cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8724cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8734cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8744cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
8754cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
8764cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
8774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8784cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8794cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8804cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
8814cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
8824cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8834cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8854cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
886e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
8874cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8884cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
8894cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
8904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
8914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
8934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
8944cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8954cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
8964cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
8974cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8984af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
899c83a29759a5c2966da5ab973e4fd90763e4c962breed    const bool completeOverwrite = info.dimensions() == size;
900c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
9014af35f348b2e2f6c428819118eb7a2f2fff53a74reed
9024cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
9034ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
9044cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
90551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9064370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
9074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
9084370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9094370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
9151f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
9174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
919687fa1c745febb57f42b0d5f03d7c1f4be2530careed            layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL);
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
921045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
923687fa1c745febb57f42b0d5f03d7c1f4be2530careed                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
9332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
9352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9362ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9372ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
938f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
9392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
9402ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
9412ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
9422ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
9432ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
9442ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
9452ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
9462ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
9472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
9482ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
9502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
9512ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
952f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
953f0090cb80ab10a49e511aa5450ae38917fa058d9reed
954f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
9552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
9562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
9572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
9582ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9592ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
9602ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
961f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
962a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
963a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
964a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
9652ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
966f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
967f0090cb80ab10a49e511aa5450ae38917fa058d9reed
968f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
9692ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9702ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
9712ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
9722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
9732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
9742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
9752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
9762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
9772ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
978a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
9792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
9802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
9812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
982f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
983f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
984f0090cb80ab10a49e511aa5450ae38917fa058d9reed
985f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
986f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
987f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
988f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
989f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
990f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
991f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
992f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
993f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
994f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
995f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
996f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
999d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
10014b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1002687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
1006b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
1008b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
1009b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
1010b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1013a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
10149b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1015bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
1016bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
1017a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
1018f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1019c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
102096e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
102196e657d0e103b8358a77ecd913f6086929f792b8reed
1022c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
102396e657d0e103b8358a77ecd913f6086929f792b8reed        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
1024c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
1025bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
102649f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
10284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
102996e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
1033bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
10349b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                fCachedLocalClipBoundsDirty = true;
10351f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
1036bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
1037a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1042180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
104489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
1045180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
10469b3aa54bc9605257c701cf465813f5fb1d7ba39ereed        fCachedLocalClipBoundsDirty = true;
1047687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1048180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
1049a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1050a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1051a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
1052a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
1053a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1054a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1055a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1056a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1057d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
1058d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
1059d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
1060d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
1061d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
1062a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
106376033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
10642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
1065d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1066d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10672ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
1068d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
1069d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
1070d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
1071e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
1072a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
107376033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, flags, strategy);
10742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
10758926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
10768926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
10772ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
107876033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                 SaveLayerStrategy strategy) {
1079b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
10802a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
1081b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
1082b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
1083a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1084a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
10852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1086a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1087a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1088a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1089a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
1090daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
10912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1094e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1095e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1096e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
10972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1098e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1099e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
110076033be81b82c44fd5d4fdf2672eb22e505da1f0reed    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
11018dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
11028dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
110376033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1104daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
110576033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
11068dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1107b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1108b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
110915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
111015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1112b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
1113b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    if (NULL == device) {
1114b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
11152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1116b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1117b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
111861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    bool forceSpriteOnRestore = false;
111961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
1120daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
112161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
112261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
112361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        if (NULL == newDev) {
112461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
11259a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
11269a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
112761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            if (NULL == newDev) {
112861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                SkErrorInternals::SetError(kInternalError_SkError,
112961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                           "Unable to create device for layer.");
113061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                return;
113161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            }
113261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            forceSpriteOnRestore = true;
113361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
113461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        device = newDev;
1135e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1136e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
11376f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
113861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip,
113986a17e7716c8db858e219a46b9db3817bb770beereed                                            forceSpriteOnRestore));
11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1147d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1148d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1149d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1150d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1166c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1168687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
11696c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
117088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
118449f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
11866f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
11878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
118861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
11898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1191b679ca8926a832274b14fdb512f88f64b61d32eareed            SkDELETE(layer);
1192b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1193b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1194a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1195b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
119788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12004a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
12014a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (NULL == props) {
12024a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
12034a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
12044a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
120576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
120676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
12074a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
120876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
12094a8126e7f81384526629b1e21bf89b632ea13cd9reed    return dev ? dev->newSurface(info, props) : NULL;
121076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
121176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1212c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1213c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1214c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1215c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1216c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1217900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1218c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1219c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1220c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1221c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1222884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1223884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onPeekPixels(&pmap)) {
1224884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1225884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1226884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1227884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1228884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1229884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1230884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1231884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1232884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.addr();
1233c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1234c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1235884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1236c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1237884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1238c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1239c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
12406b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1241884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1242884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
1243884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1244884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1245884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1246884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1247884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1248884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1249884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1250884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1251884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
12526b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
12536b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1254884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
12559c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12569c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1257884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
12589c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1259884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
12609c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12619c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1262c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1263c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1264c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1265c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1266848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1267c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1268c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1269c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1270c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1271c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1272c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1273c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1274c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1275c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1276c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1277c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1278c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1279c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
128000f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1281c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1282c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1283c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1284c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1285c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1286c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1287520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
12889bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
129050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12942c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12962c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12989bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12999bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
13009bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
130178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
130278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
130378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
130478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
130578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
130678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
130778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
130878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
130978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
13109bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
13119bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
13129bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
13139bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
13149bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
13159bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13181f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
131961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13244b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13271f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
132876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
132976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
133076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
1332efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips            SkImageFilter::Proxy proxy(dstDev);
133376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
13346776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1335b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1336fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1337d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
13384cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1339be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
134055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
13414cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
13425efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13435efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13446776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13456776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
134676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
134761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        } else if (deviceIsBitmapDevice) {
13489572a10c9a6a868bbb8f71d7806d0a45f183333freed            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
134961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
135076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1351b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
135276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
13580acf1b4b3645772d220c720313821bac389751b5reed    if (gTreatSpriteAsBitmap) {
13590acf1b4b3645772d220c720313821bac389751b5reed        this->save();
13600acf1b4b3645772d220c720313821bac389751b5reed        this->resetMatrix();
13610acf1b4b3645772d220c720313821bac389751b5reed        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
13620acf1b4b3645772d220c720313821bac389751b5reed        this->restore();
13630acf1b4b3645772d220c720313821bac389751b5reed        return;
13640acf1b4b3645772d220c720313821bac389751b5reed    }
13650acf1b4b3645772d220c720313821bac389751b5reed
13669881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
136750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
13688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
13698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
137050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1371fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
13738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
13748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
13758926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1376fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13778926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1378fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
13808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
13818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
13828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1384efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips            SkImageFilter::Proxy proxy(iter.fDevice);
13858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
13866776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1387fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1388d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1389f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary            const SkIRect clipBounds = bitmap.bounds();
1390be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
139155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
13924cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
13935efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13945efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13956776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13965efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
13978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
13988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
13998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
14008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
14018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
14028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
14038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
14048926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
140692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1407d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1408d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1409d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1413d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1414d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1415d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1419d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1420d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1421d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
142492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1425d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1426d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1427d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
142844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
142944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
143092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1431d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1432d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1433d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1434d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
14352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1437c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14381f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
143944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
144044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
144144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
144244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
144386a17e7716c8db858e219a46b9db3817bb770beereedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
144486a17e7716c8db858e219a46b9db3817bb770beereed    this->checkForDeferredSave();
14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1446c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14471f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
144844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
14534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1460759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
14612ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
14648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1467da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1468da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
14691f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1470da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1471da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1472da17f758442f16747af39f8fbaed9c097048519creed@google.com
14733b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1474da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1475c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1476da17f758442f16747af39f8fbaed9c097048519creed@google.com
1477687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
14781f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1479da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1480da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1481da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1482da17f758442f16747af39f8fbaed9c097048519creed@google.com
14835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1486c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14898f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14911f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1492123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
149398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
149498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
149598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14981f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
1499687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1500d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1502123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
150398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
150498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
150598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
15098f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
151373e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
151473e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1515d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1516819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1517819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1518759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
15192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
15228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
15238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15248f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
15254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
15268f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
152714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
15288f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
152914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
15301f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
153114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
153214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
153314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
153414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
15358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
15368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
15378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
153814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1539687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
154014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
154114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
154214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
154314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
154473e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
154614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
154714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
154814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
154914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
155014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
15518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
15524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
15534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1554759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
15552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
15588f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
15598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
15608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
15628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1566da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1567da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
15681f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1569da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1570da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1571fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15723b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1573da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1574c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1575fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1576687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
15771f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1578da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1579da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1580da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1581da17f758442f16747af39f8fbaed9c097048519creed@google.com
15825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1585c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
15878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
15888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
15911f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1593fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1594fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1595fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1596fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1597fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1598fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1599fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1600fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1601fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1602fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
16035c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1604687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
16055c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
160645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
16071a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
16081a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
16091a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
161045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
16111a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
161245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
161345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
161445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
161573e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
16168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1618759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
16192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
16245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16255c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1627c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16295c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
16305c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1631687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
16325c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16331f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1636819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1637819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1638819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
16391f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1640ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
16415c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1642ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1643ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1644ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1645819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1646819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1647d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1648819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1649687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
16508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
16518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
16528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
16538182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
16548182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
16558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
16568182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16578182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
16588182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
16598182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16609cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
16619cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
16629cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
166373e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
16649cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
16659cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1666819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1667819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1668819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1669819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1670819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
167190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1672687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
16738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
16748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
16758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1676c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
167790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
167890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
167990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
16805c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
16815c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1682754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
16831f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1684754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1685754de5f65b466f721d952a379194cc94de376f42reed@google.com
16865c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
16871f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
16885c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16895c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16903b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
16911607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1692116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1693116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
16941f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16981f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1699a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
17001f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1701b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1702a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1703c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1704d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1705a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1706c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1707c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1708a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1709a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1710c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1711a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1712a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1713a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17173b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
17183b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17213b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1722bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
17238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1727d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1728d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
17291f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
173072dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
173172dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
173272dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1733d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1734d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1735d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
173649f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1737bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
17383b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
17393b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1740fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
17418f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
17428f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
17491f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1750bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1751bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1752bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1753bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1754bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1755bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1756bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
175749f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1758bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1759bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1760bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1761bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1762bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
17641f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17675c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
17681f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
17695c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17705c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17719c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
17729c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
17739c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
17749c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
17759c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1776644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1777644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1778644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
177949f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1780644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
178149f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1782644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1783644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1784644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1785644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1786644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1787644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1788644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1789644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1790e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1791ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1792ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
17939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1794ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1795ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1796ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1797ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1798ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1799ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1800ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1801ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1802ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1803ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1804ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1805ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1806ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1807ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1808ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1809ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1810ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1811ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
181241af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
181341af966ab338e95eee81ab618ab28195075338f7reed
181441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
181541af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
181641af966ab338e95eee81ab618ab28195075338f7reed}
181741af966ab338e95eee81ab618ab28195075338f7reed
181841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
181941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
182041af966ab338e95eee81ab618ab28195075338f7reed}
182141af966ab338e95eee81ab618ab28195075338f7reed
182241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
182341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
182441af966ab338e95eee81ab618ab28195075338f7reed}
182541af966ab338e95eee81ab618ab28195075338f7reed
182641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
182741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
182841af966ab338e95eee81ab618ab28195075338f7reed}
182941af966ab338e95eee81ab618ab28195075338f7reed
183041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
183141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
183241af966ab338e95eee81ab618ab28195075338f7reed}
183341af966ab338e95eee81ab618ab28195075338f7reed
183441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
183541af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
183641af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
183741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
183841af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
183941af966ab338e95eee81ab618ab28195075338f7reed}
184041af966ab338e95eee81ab618ab28195075338f7reed
184141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
184241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
184341af966ab338e95eee81ab618ab28195075338f7reed}
184441af966ab338e95eee81ab618ab28195075338f7reed
1845a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1846a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
184741af966ab338e95eee81ab618ab28195075338f7reed}
184841af966ab338e95eee81ab618ab28195075338f7reed
1849e47829b6b1eeb6b0c97ccb3df3016d197046824creed#ifdef SK_SUPPORT_LEGACY_SRCPTR_DRAWIMAGERECT
185041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1851a5517e2b190a8083b38964972b031c13e99f1012reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1852a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (dst.isEmpty()) {
1853a85d4d0814818e4ddabb9237da209d61d6cd5854reed        return;
1854a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
1855562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->onDrawImageRect(image, src, dst, paint, constraint);
185641af966ab338e95eee81ab618ab28195075338f7reed}
1857e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1858e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              const SkPaint* paint, SrcRectConstraint constraint) {
1859e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty()) {
1860e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1861e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1862e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, src, dst, paint, constraint);
1863e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1864e47829b6b1eeb6b0c97ccb3df3016d197046824creed#endif
1865e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1866e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1867e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1868e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1869e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1870e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1871e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1872e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
187341af966ab338e95eee81ab618ab28195075338f7reed
187484984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
187584984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1876e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
187784984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
187884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1879e47829b6b1eeb6b0c97ccb3df3016d197046824creed#ifdef SK_SUPPORT_LEGACY_SIMPLE_DRAWIMAGERECT
1880e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint) {
1881e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint);
1882e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1883e47829b6b1eeb6b0c97ccb3df3016d197046824creed#else
1884e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1885e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1886e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1887e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1888e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1889e47829b6b1eeb6b0c97ccb3df3016d197046824creed#endif
1890e47829b6b1eeb6b0c97ccb3df3016d197046824creed
18914c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
18924c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
18934c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
18944c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
18954c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
18964c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
1897e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
18984c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
18994c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->onDrawImageNine(image, center, dst, paint);
19004c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
19014c21dc5ddf3b482293ed34eead876d8d61a662c3reed
190241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
19034c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
19042df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19052df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
190641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
190741af966ab338e95eee81ab618ab28195075338f7reed}
190841af966ab338e95eee81ab618ab28195075338f7reed
1909e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1910a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1911e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1912a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1913a5517e2b190a8083b38964972b031c13e99f1012reed    }
1914e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
191541af966ab338e95eee81ab618ab28195075338f7reed}
191641af966ab338e95eee81ab618ab28195075338f7reed
191784984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
191884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1919e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1920e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1921e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1922e47829b6b1eeb6b0c97ccb3df3016d197046824creed#ifdef SK_SUPPORT_LEGACY_SIMPLE_DRAWIMAGERECT
1923e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint) {
1924e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint);
1925e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1926e47829b6b1eeb6b0c97ccb3df3016d197046824creed#else
1927e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1928e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
1929e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1930e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
193184984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
1932e47829b6b1eeb6b0c97ccb3df3016d197046824creed#endif
193384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
193441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
193541af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
19364c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
19372df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19382df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
19394c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
1940a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
19414c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
194241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapNine(bitmap, center, dst, paint);
194341af966ab338e95eee81ab618ab28195075338f7reed}
194441af966ab338e95eee81ab618ab28195075338f7reed
194541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
19464c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
19472df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19482df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
194941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawSprite(bitmap, left, top, paint);
195041af966ab338e95eee81ab618ab28195075338f7reed}
195141af966ab338e95eee81ab618ab28195075338f7reed
195271c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
195371c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkColor colors[], int count, SkXfermode::Mode mode,
195471c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
195571c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
195671c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
195771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
195871c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(atlas);
195971c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(xform);
196071c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
196171c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
196271c3c760a83123ee0b3127b8c65c6394ce541c50reed}
196371c3c760a83123ee0b3127b8c65c6394ce541c50reed
1964e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1965e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
1966e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1967e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
1968e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1969e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1970e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
1971e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1972e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1973e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1974e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
1975e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1976e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1977e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1978e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1979e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
1980e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1981e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1982e47829b6b1eeb6b0c97ccb3df3016d197046824creed
19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
198849f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
198928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
199028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
199128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
199228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
199341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
19949881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1995fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1996fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1997fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1998fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
1999c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, NULL, false)
20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
200841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
200941af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
20109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
201578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
201678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
2017a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
2018a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
2019a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
2020a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
2021a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
2022a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
2023a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
202478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
202578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
2026a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
2027a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
2028fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
2029a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
203278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
20334b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
20368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
20429881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
204378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
204478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
20468432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
20478432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
20488432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
20498432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
20508432808ad8898ac7137bc7ce1d9df6005e866401reed
20518432808ad8898ac7137bc7ce1d9df6005e866401reed        bounds = &paint.computeFastBounds(tmp, &storage);
205278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20564b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2057c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
20618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20634e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
206641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
20679881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
206878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
206978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
207178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
207278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
20744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
20754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2076306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
207778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
207846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
207946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
208046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
208146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
208246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
208346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20854ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
208641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
20879881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
208878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
208978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
209178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
209278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
20944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
20954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
20964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
20984ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
20994ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2100f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2101f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
21024ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2103f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2104f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
21054ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2106f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
210778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2108f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2109f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2110f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2111f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2112f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2113f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
21144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
21154ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2116ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2117ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
2118ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
2119ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
2120ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
2121ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
2122ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
2123ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
2124ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
2125ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
212625c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2127ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
212825c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2129ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2130ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2131ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
213225c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2133ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2134ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
21354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
213641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
21379881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
21389364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
21399364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
21409364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
21419364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
214278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
214378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
2144fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
214578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
214678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
214778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
21488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21510b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
21520b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
21530b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
21546803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2155fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
2156fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2157fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
2158fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
216078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21634e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2169a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
21709881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2171a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2172a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2173a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2174a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2175a85d4d0814818e4ddabb9237da209d61d6cd5854reed            paint->computeFastBounds(bounds, &bounds);
2176a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2177a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(bounds)) {
2178a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2179a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2180a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2181a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2182a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2183a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2184a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2185a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2186a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2187a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
2188a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2189a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2190a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImage(iter, image, x, y, looper.paint());
2191a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2192a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2193a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2194b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2195b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
219641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2197562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
21989881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2199a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect storage;
2200a85d4d0814818e4ddabb9237da209d61d6cd5854reed    const SkRect* bounds = &dst;
2201a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2202a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2203a85d4d0814818e4ddabb9237da209d61d6cd5854reed            bounds = &paint->computeFastBounds(dst, &storage);
2204a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2205a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(*bounds)) {
2206a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2207a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2208a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2209a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2210a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2211a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2212a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2213a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2214c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, bounds,
2215c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
2216a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2217a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2218a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2219a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2220a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2221a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2222b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2223b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
222441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
22259881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22283d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
22299efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
22309efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
22319efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
22329efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
22339efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
22349efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
22359efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
22369efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
22373b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
22438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
22449bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22479987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
22487112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2249eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2250a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
225150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
22528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
225474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
225578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
225678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
22573d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
22589efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
22599efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
22609efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
22613b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
22623d60812865bb034851da777a91413ab584929887reed@google.com            return;
22633d60812865bb034851da777a91413ab584929887reed@google.com        }
22648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22653d60812865bb034851da777a91413ab584929887reed@google.com
226633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
226733535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
226833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22707064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2271c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, bounds,
2272c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
22737064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
227433535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2275562fe4767cc73e08a4e039362bc0336aea66ecfbreed        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2276f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
22777064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
227833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2282562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
22839881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
22849987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2285562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
22869987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22879987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22884c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
22894c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
22904c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
22914c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22924c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkRect storage;
22934c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const SkRect* bounds = &dst;
22943d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
229560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
229660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
229760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
22983b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
22993d60812865bb034851da777a91413ab584929887reed@google.com            return;
23003d60812865bb034851da777a91413ab584929887reed@google.com        }
23013d60812865bb034851da777a91413ab584929887reed@google.com    }
23024c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23034c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
23044c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (NULL == paint) {
23054c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23064c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23074c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23084c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
23094c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23104c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
23114c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
23129987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
23134c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23144c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23159987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23169987ec3791336bad6af5cbe513564786b2df55aareed@google.com
231741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
231841af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
23199881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
23209987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
23219987ec3791336bad6af5cbe513564786b2df55aareed@google.com
23224c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkRect storage;
23234c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const SkRect* bounds = &dst;
23244c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (NULL == paint || paint->canComputeFastBounds()) {
23254c21dc5ddf3b482293ed34eead876d8d61a662c3reed        if (paint) {
23264c21dc5ddf3b482293ed34eead876d8d61a662c3reed            bounds = &paint->computeFastBounds(dst, &storage);
23274c21dc5ddf3b482293ed34eead876d8d61a662c3reed        }
23284c21dc5ddf3b482293ed34eead876d8d61a662c3reed        if (this->quickReject(*bounds)) {
23294c21dc5ddf3b482293ed34eead876d8d61a662c3reed            return;
23304c21dc5ddf3b482293ed34eead876d8d61a662c3reed        }
23314c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23324c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23334c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
23344c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (NULL == paint) {
23354c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23364c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23374c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23384c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
23394c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23404c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
23414c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
23424c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23434c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23444c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23459987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23469987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2347f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2348f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
23491f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2350112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2351112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2352a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2353112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2354f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2355f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2356f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2357f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2358f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2359f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2360f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2361f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2362f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
23632c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
23642c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2365f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2366f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
236752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
236852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
236917b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
237052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
237152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
237252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
237317b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
237452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
237552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
237652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
237752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
237852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
237952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
238052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
238152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
238252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
238352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
238452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
238552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
238652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
238752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
238852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
238952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
239052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
239152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
239252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
239352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
239452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
239552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
239652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
239752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
239852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
239952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
240052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
240152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
240252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
240352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
240452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
240552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
240652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
240752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
240852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
240952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
241052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
241152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
241252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
241352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
241452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
241552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
241652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
241752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
241852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
241952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
242052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
242152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
242252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
242352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
242452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
242552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
242652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
242752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
242852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
242952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
243052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
243152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
243252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
243352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
243452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
243552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
243652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
243752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
243852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2439e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2440e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
244178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
24428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2445f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
244652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
244752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
24488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2453e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2454e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
245505c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
245605c4a4322e7d4f3417b7df33825bab8603d52051fmalita
245778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
245887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
246105c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2462f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2464b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2469e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
247005c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247105c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
247205c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
247487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
247705c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2478f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2480b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2484e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2485e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
248678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
248787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
24904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
24918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2492b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2493945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
24944325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
24954325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
249600d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
249700d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
24987ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
249985d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
250085d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    const SkRect* bounds = NULL;
250119653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
250285d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
250385d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        bounds = &paint.computeFastBounds(storage, &storage);
25047ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
250585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        if (this->quickReject(*bounds)) {
25067ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita            return;
25077ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        }
25087ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
25097ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2510024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2511024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2512024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
2513024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = NULL;
2514024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
251585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
251600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2517aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2518aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2519024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
252000d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
252100d5c2c6523321d25b32905ff4822f083a4173eefmalita
2522aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2523024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2524024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
252500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
252600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2527e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2528e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2529e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
25309881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2531e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2532e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2533e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2534e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
25359881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2536e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2537e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2538e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2539e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
25409881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2541e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2542e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2543e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2544e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
25459881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2546e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2547e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
254800d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
254900d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
25509881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
255149f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
255200d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
255300d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
255400d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2555e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
255641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
255741af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
255841af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
255941af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
256041af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
25619881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
256278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
25634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
25664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
25674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
25688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2573b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2574b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
25759881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2576b3c9d1c33caf325aada244204215eb790c228c12dandov    if (NULL == cubics) {
2577b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2578b3c9d1c33caf325aada244204215eb790c228c12dandov    }
25796cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2580ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2581ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2582ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2583b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2584ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2585ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2586ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
25876cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2588b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2589b3c9d1c33caf325aada244204215eb790c228c12dandov}
2590b3c9d1c33caf325aada244204215eb790c228c12dandov
2591b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2592b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2593b3c9d1c33caf325aada244204215eb790c228c12dandov
2594ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
25956cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2596ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2597b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2598ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
25996cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2600ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2601ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2602ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2603a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2604a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (dr) {
2605a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        if (x || y) {
2606a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2607a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            this->onDrawDrawable(dr, &matrix);
2608a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        } else {
2609a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            this->onDrawDrawable(dr, NULL);
2610a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        }
2611a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2612a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2613a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2614a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2615a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (dr) {
2616a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        if (matrix && matrix->isIdentity()) {
2617a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            matrix = NULL;
2618a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        }
2619a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        this->onDrawDrawable(dr, matrix);
26206a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
26216a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26226a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2623a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2624a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    SkRect bounds = dr->getBounds();
2625a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (matrix) {
2626a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        matrix->mapRect(&bounds);
2627a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2628a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (this->quickReject(bounds)) {
2629a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        return;
2630a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2631a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
26326a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26336a070dc06af4e9f305f9d08a69e34d18ade473cbreed
263471c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
263571c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkColor colors[], int count, SkXfermode::Mode mode,
263671c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
263771c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
263871c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
263971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
264071c3c760a83123ee0b3127b8c65c6394ce541c50reed
264171c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
264271c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
264371c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
264471c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
264571c3c760a83123ee0b3127b8c65c6394ce541c50reed
264671c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, NULL)
264771c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
264871c3c760a83123ee0b3127b8c65c6394ce541c50reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
264971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
265071c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
265171c3c760a83123ee0b3127b8c65c6394ce541c50reed}
265271c3c760a83123ee0b3127b8c65c6394ce541c50reed
26538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
26558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
26568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2659845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
26609881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
26618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2664845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
26650baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
26668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
26688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2670845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
26719881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
26728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2675845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
26760baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
26778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
26798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
26829881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
26838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
26844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
26868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
26878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
26909881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
26918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
26928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
26958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
26968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
26978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
27008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
27019881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
27028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
27034b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
27058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
27068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
27078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
27108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
27129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
27138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
27168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
27178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
27219881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
27228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
27248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
27284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
27298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
27328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
27339881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
27348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
27358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
27368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
27373b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
27388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
27398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
27408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
27424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
27434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
27468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
27508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
27518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
27529881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
27538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
27548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
27558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
27578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
27588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
27598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
27618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
27638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
27658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
27698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
27719881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
27728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
27734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
27758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
27768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2778f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
27791c2c441fede0ae9573afc098017011e3439624a9reed
27801c2c441fede0ae9573afc098017011e3439624a9reed/**
27811c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
27821c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
27831c2c441fede0ae9573afc098017011e3439624a9reed *
27841c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
27851c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
27861c2c441fede0ae9573afc098017011e3439624a9reed */
27871c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
27889b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2789d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
27901c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
279149f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2792d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
2793d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            matrix = NULL;
2794d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
27951c2c441fede0ae9573afc098017011e3439624a9reed        if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
27961c2c441fede0ae9573afc098017011e3439624a9reed            SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
27971c2c441fede0ae9573afc098017011e3439624a9reed            picture->playback(this);
27981c2c441fede0ae9573afc098017011e3439624a9reed        } else {
27991c2c441fede0ae9573afc098017011e3439624a9reed            this->onDrawPicture(picture, matrix, paint);
28001c2c441fede0ae9573afc098017011e3439624a9reed        }
2801d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2802d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
28039b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2804d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2805d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2806145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
280749f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2808145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2809145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2810d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2811145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2812145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2813145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2814145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2815a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2816c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
28178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2823d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
28248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
28268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
28288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
28328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
28338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
28368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28391f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
28418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
28448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
28458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
28488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
28498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
28508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
28518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
28538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
28568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
28578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
285820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
285920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
286020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2861c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
28623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
28643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
28663107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
28673107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
28683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
28693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28713107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28723107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28733107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
28753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
28763107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
287728fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
28783107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28793107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28823107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28833107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
28843107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
28853107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
288642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
288742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
288842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
288942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2890eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
289142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
289242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
289342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
289442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
289542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
289642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2897d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2898d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2899d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2900d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2901a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2902d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2903d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2904d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
290549f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2906a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2907d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2908a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2909d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2910a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
291149f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2912d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2913d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
29146cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
291549f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2916d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2917d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2918d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2919d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2920d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2921d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2922d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2923