SkCanvas.cpp revision c83a29759a5c2966da5ab973e4fd90763e4c962b
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
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
9d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
11dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
133cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
165f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkErrorInternals.h"
17b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
1874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
194c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkNinePatchIter.h"
20c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
2145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
22b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
240017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
2596472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
307ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
32a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
338f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
37644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
38644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
39644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
40c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
41c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
42c83a29759a5c2966da5ab973e4fd90763e4c962breed *
43c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
44c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
45c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
46c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
47c83a29759a5c2966da5ab973e4fd90763e4c962breed */
48c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
49c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
50c83a29759a5c2966da5ab973e4fd90763e4c962breed    SK_COMPILE_ASSERT((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
51c83a29759a5c2966da5ab973e4fd90763e4c962breed                      (int)kNone_ShaderOverrideOpacity,
52c83a29759a5c2966da5ab973e4fd90763e4c962breed                      need_matching_enums0);
53c83a29759a5c2966da5ab973e4fd90763e4c962breed    SK_COMPILE_ASSERT((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
54c83a29759a5c2966da5ab973e4fd90763e4c962breed                      (int)kOpaque_ShaderOverrideOpacity,
55c83a29759a5c2966da5ab973e4fd90763e4c962breed                      need_matching_enums1);
56c83a29759a5c2966da5ab973e4fd90763e4c962breed    SK_COMPILE_ASSERT((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
57c83a29759a5c2966da5ab973e4fd90763e4c962breed                      (int)kNotOpaque_ShaderOverrideOpacity,
58c83a29759a5c2966da5ab973e4fd90763e4c962breed                      need_matching_enums2);
59c83a29759a5c2966da5ab973e4fd90763e4c962breed
60c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
61c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
62c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (!this->getClipStack()->quickContains(bounds)) {
63c83a29759a5c2966da5ab973e4fd90763e4c962breed        return false;
64c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
65c83a29759a5c2966da5ab973e4fd90763e4c962breed
66c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
67c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!this->getTotalMatrix().rectStaysRect()) {
68c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
69c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
70c83a29759a5c2966da5ab973e4fd90763e4c962breed
71c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkRect devRect;
72c83a29759a5c2966da5ab973e4fd90763e4c962breed        this->getTotalMatrix().mapRect(&devRect, *rect);
73c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (devRect.contains(bounds)) {
74c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
75c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
76c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
77c83a29759a5c2966da5ab973e4fd90763e4c962breed
78c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
79c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
80c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
81c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
82c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
83c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
84c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
85c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
86c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
87c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
88c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
89c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
90c83a29759a5c2966da5ab973e4fd90763e4c962breed}
91c83a29759a5c2966da5ab973e4fd90763e4c962breed
92c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
93c83a29759a5c2966da5ab973e4fd90763e4c962breed
94d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
95d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
96d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
97d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
98d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
99d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
100d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
101d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1020acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1030acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1040acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1050acf1b4b3645772d220c720313821bac389751b5reed}
1060acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1070acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1080acf1b4b3645772d220c720313821bac389751b5reed}
1090acf1b4b3645772d220c720313821bac389751b5reed
110da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
111da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
11215e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1362c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1372c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
138c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
13997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
140c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
141c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
142c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
143c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
144c83a29759a5c2966da5ab973e4fd90763e4c962breed}
145c83a29759a5c2966da5ab973e4fd90763e4c962breed
146c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
147c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
148c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
149c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
150c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
151c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
152c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
153c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
154c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
155c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
156c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
157c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
158c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
159c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
16097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
16197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
16297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1654a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
1664a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
1674a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
1684a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
1694a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1704a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
1714a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
1724a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1734a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
1744a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1754a8126e7f81384526629b1e21bf89b632ea13cd9reed
1764a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
1774a8126e7f81384526629b1e21bf89b632ea13cd9reed
1781f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1871f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1896f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
19061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
19161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
19261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const bool          fDeviceIsBitmapDevice;
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19496e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
19586a17e7716c8db858e219a46b9db3817bb770beereed             bool conservativeRasterClip, bool deviceIsBitmapDevice)
196d954498c01ccf0417feacf89e45d0c62a06a813breed        : fNext(NULL)
197d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
19861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
199d954498c01ccf0417feacf89e45d0c62a06a813breed    {
200d954498c01ccf0417feacf89e45d0c62a06a813breed        if (NULL != device) {
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
20240a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2044b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
20688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
20949f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
21040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
21388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
21488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
216feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
217feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
218feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
219feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
220feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
221feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
222feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
223045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
224045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
2256f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
2266f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
2294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
2384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
242045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
2454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
247045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2513fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
2523fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
260f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2721f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
273d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
285d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
286d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter     = NULL;
287d954498c01ccf0417feacf89e45d0c62a06a813breed        fLayer      = NULL;
288d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer   = NULL;
2892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
291b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
292d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
293d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
294d954498c01ccf0417feacf89e45d0c62a06a813breed    }
2952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
296d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
298d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
2992ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
300b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
30582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
309feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
310feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
311feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
312feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
313feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
314feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
315feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
316feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
317feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3228a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
3234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
3248a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
327687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
3298a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3314b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
340f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
341f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
344045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
345045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
34741e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
34841e010cb901c0da9066c4df562030808c9ccd7f8reed                fDst.reset(fDevice->imageInfo(), NULL, 0);
34941e010cb901c0da9066c4df562030808c9ccd7f8reed            }
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
351f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
355199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3604b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3611f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3626f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3636f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3676f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
379dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
380dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
381dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
382dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
383dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
384dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
385dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  colorfilter, else return NULL.
386dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
387dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkColorFilter* image_to_color_filter(const SkPaint& paint) {
388dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
389dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
390dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
391dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
392dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
393dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* imgCF;
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf->asAColorFilter(&imgCF)) {
395dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
396dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
397dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
398dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (NULL == paintCF) {
400dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
401dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
402dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
404dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
405dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
406dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
407dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
408dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
409dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
4124a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
41378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
41478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
4154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4174a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4195c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
422dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
423dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
424dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
425dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setColorFilter(simplifiedCF)->unref();
426dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setImageFilter(NULL);
427dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
428dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
429dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
430dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4315c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4325c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4335c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4345c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4355c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4365c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4375c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4385c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4395c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4405c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4415c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4425c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4435c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4445c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4455c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
447dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
448dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setXfermode(fPaint->getXfermode());
449e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
45076033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4515c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
4525c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
4538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
45579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
45679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
45779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
45879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
459129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
460129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
46179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
462129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
4635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
465b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
4664a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
4674a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
4684a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
469dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
4704a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
4714a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
4724a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
4734a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
47574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
4775c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
4788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
4798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
48274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
4844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
4854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
4864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
48774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
488129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
489129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
490129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
491129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
492129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
493129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
494129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
495129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
496129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
497fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
49874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
500dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
501dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5022c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5032c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5042c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5052c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5062c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5074a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
5085c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5092c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
510129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
51179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
51279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
513129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
514129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
517129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
518632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
519129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5205c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
521632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
522dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
523dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5244a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
5258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5265c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
527129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
5285c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        paint->setXfermode(NULL);
529129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
53179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
532129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
533129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
534129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
535129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
536971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
537971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
538971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
539971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
54079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
541129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
542632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
543632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
544129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
545129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
547129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
54879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5494e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5514e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
552632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
553632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
5544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
5554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5574e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5628926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
56397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5644a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
5658926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
5668926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
5678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
56878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
56997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5704a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
5714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
5734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
574c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
575c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
576c83a29759a5c2966da5ab973e4fd90763e4c962breed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
577c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
578c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
579c83a29759a5c2966da5ab973e4fd90763e4c962breed
5804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
584feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
585feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
586feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBounds.setEmpty();
587feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBoundsDirty = true;
588feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
589feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
590feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
591feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
592feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
593feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
594feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
595feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
596d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
597d954498c01ccf0417feacf89e45d0c62a06a813breed    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
598c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
599c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
6008f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
60145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
602f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
6032ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
60474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
606687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack.reset(SkNEW(SkClipStack));
607687fa1c745febb57f42b0d5f03d7c1f4be2530careed
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
609d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
611a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
612a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
61386a17e7716c8db858e219a46b9db3817bb770beereed    new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false);
614b679ca8926a832274b14fdb512f88f64b61d32eareed
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
61797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
618f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
619f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
620efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
621efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
6224a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (device->forceConservativeRasterClip()) {
6234a8126e7f81384526629b1e21bf89b632ea13cd9reed            fConservativeRasterClip = true;
6244a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
625f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
626f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
62778e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
628f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
629f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
632cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
633e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6344a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
635e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6368d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
637ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
638d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(NULL, kDefault_InitFlags);
6398d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6408d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
641d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
642d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
643d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
644d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
645d954498c01ccf0417feacf89e45d0c62a06a813breed}
646d954498c01ccf0417feacf89e45d0c62a06a813breed
647d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
648d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
649fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
650fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
65178e276889795454891cbba48ab11927968114953reed    {
65278e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
65378e276889795454891cbba48ab11927968114953reed    }
654d954498c01ccf0417feacf89e45d0c62a06a813breed
655d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
656b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
657d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
658d954498c01ccf0417feacf89e45d0c62a06a813breed};
659d954498c01ccf0417feacf89e45d0c62a06a813breed
66096a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
661e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
66296a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
663e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
664e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
665b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
66678e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
667fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips                          (SkIRect::MakeWH(width, height), fProps)), kDefault_InitFlags)->unref();
668d954498c01ccf0417feacf89e45d0c62a06a813breed}
669e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
67078e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
671d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6724a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
673d954498c01ccf0417feacf89e45d0c62a06a813breed{
674d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
675b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
676fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds, fProps)), flags)->unref();
67727a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
679d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
680d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6817b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
682d954498c01ccf0417feacf89e45d0c62a06a813breed{
683d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
684b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
685d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
688fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
689fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6907b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
691fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
692fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
693fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
694fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
695fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
696fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
6974a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
6983716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6994a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
7003716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7013716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
702b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
703fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap, fProps)));
7044a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7054a8126e7f81384526629b1e21bf89b632ea13cd9reed}
70629c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
7074a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
7084a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7094a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
7104a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7114a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
712b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
713fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap, fProps)));
7144a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7207c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
724b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
73351985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
73874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
73974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
74074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
74174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
74274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
74374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
74474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
74574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
74674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
749bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
7501f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
751bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
752bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
753bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
754bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
755bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
7564ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
7574ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
7584ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
7594ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
7604ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
7614ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
7624ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
7634ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
7644ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
7654ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
7664ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
7671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
768210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
769210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
770210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
7711f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
773c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7781f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
7790b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
7800b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
7810b53d59a24f667350b4282f88470713902409030reed@google.com    }
7829266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
7839266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
7849266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
785a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
786a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
787a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
788a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
789a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
790a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
791a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
792848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
793a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
794a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
795a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
796a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
797a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
798cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
799cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
800cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
801cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
802cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
803cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
804a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
805a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
806a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
807a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
808a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
809a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
810a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
81151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
812c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
813a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
814a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
815a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
816a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
817ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
818ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
81974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
820848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
821a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
822a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
823a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
824a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
825a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
826daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
827c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
828a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
829a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
830c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
83196472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
832a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
833a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
834a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
835a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
836a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
837f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
83896472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
83996472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
840a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
841a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
842db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
843a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
84496472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
84551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
84651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
8484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
8494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
851cf01e31df6bbda270dca2ee3b4967caf51e465dcreed
852cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
853cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
854cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
855cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
8564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
8584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
8594cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
8614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
8624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
8634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
8644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
8654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
8664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
8674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
8684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8694cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
8704cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8714cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8724cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8734cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
8744cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
8754cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
8764cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8784cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8794cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
8804cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
8814cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8824cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8834cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
885e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
8864cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8874cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
8884cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
8894cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
8904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
8924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
8934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8944cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
8954cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
8964cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8974af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
898c83a29759a5c2966da5ab973e4fd90763e4c962breed    const bool completeOverwrite = info.dimensions() == size;
899c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
9004af35f348b2e2f6c428819118eb7a2f2fff53a74reed
9014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
9024ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
9034cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
90451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9054370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
9064370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
9074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9084370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
9141f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
9164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
918687fa1c745febb57f42b0d5f03d7c1f4be2530careed            layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL);
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
922687fa1c745febb57f42b0d5f03d7c1f4be2530careed                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9312ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
9322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
9342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9362ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
937f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
9382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
9392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
9402ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
9412ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
9422ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
9432ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
9442ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
9452ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
9462ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
9472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9482ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
9492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
9502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
951f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
952f0090cb80ab10a49e511aa5450ae38917fa058d9reed
953f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
9542ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
9552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
9562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
9572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9582ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
9592ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
960f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
961a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
962a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
963a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
9642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
965f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
966f0090cb80ab10a49e511aa5450ae38917fa058d9reed
967f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
9682ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9692ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
9702ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
9712ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
9722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
9732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
9742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
9752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
9762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
977a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
9782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
9792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
9802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
981f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
982f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
983f0090cb80ab10a49e511aa5450ae38917fa058d9reed
984f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
985f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
986f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
987f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
988f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
989f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
990f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
991f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
992f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
993f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
994f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
995f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
998d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
10004b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1001687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
1005b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
1007b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
1008b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
1009b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1012a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
10139b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1014bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
1015bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
1016a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
1017f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1018c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
101996e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
102096e657d0e103b8358a77ecd913f6086929f792b8reed
1021c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
102296e657d0e103b8358a77ecd913f6086929f792b8reed        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
1023c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
1024bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
102549f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
10274b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
102896e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
1032bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
10339b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                fCachedLocalClipBoundsDirty = true;
10341f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
1035bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
1036a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1041180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
104389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
1044180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
10459b3aa54bc9605257c701cf465813f5fb1d7ba39ereed        fCachedLocalClipBoundsDirty = true;
1046687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1047180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
1048a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1049a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1050a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
1051a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
1052a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1053a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1054a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1055a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1056d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
1057d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
1058d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
1059d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
1060d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
1061a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
106276033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
10632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
1064d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1065d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
1067d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
1068d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
1069d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
1070e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
1071a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
107276033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, flags, strategy);
10732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
10748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
10758926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
10762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
107776033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                 SaveLayerStrategy strategy) {
1078b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
10792a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
1080b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
1081b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
1082a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1083a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
10842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1085a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1086a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1087a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1088a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
1089daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
10902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1093e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1094e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1095e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
10962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1097e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1098e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
109976033be81b82c44fd5d4fdf2672eb22e505da1f0reed    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
11008dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
11018dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
110276033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1103daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
110476033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
11058dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1106b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1107b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
110815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
110915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1111b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
1112b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    if (NULL == device) {
1113b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
11142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1115b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1116b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
111761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    bool forceSpriteOnRestore = false;
111861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
1119daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
112061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
112161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
112261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        if (NULL == newDev) {
112361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
11249a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
11259a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
112661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            if (NULL == newDev) {
112761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                SkErrorInternals::SetError(kInternalError_SkError,
112861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                           "Unable to create device for layer.");
112961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                return;
113061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            }
113161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            forceSpriteOnRestore = true;
113261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
113361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        device = newDev;
1134e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1135e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
11366f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
113761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip,
113886a17e7716c8db858e219a46b9db3817bb770beereed                                            forceSpriteOnRestore));
11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1146d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1147d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1148d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1149d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1165c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1167687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
11686c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
116988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
118349f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
11856f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
11868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
118761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
11888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1190b679ca8926a832274b14fdb512f88f64b61d32eareed            SkDELETE(layer);
1191b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1192b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1193a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1194b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
119688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11994a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
12004a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (NULL == props) {
12014a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
12024a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
12034a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
120476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
120576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
12064a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
120776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
12084a8126e7f81384526629b1e21bf89b632ea13cd9reed    return dev ? dev->newSurface(info, props) : NULL;
120976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
121076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1211c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1212c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1213c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1214c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1215c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1216900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1217c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1218c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1219c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1220c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1221884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1222884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onPeekPixels(&pmap)) {
1223884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1224884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1225884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1226884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1227884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1228884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1229884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1230884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1231884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.addr();
1232c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1233c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1234884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1235c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1236884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1237c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1238c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
12396b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1240884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1241884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
1242884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1243884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1244884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1245884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1246884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1247884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1248884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1249884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1250884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
12516b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
12526b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1253884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
12549c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12559c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1256884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
12579c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1258884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
12599c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12609c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1261c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1262c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1263c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1264c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1265848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1266c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1267c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1268c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1269c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1270c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1271c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1272c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1273c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1274c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1275c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1276c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1277c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1278c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
127900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1280c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1281c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1282c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1283c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1284c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1285c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1286520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
12879bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
128950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12932c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12952c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12979bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12989bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
12999bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
130078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
130178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
130278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
130378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
130478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
130578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
130678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
130778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
130878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
13099bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
13109bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
13119bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
13129bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
13139bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
13149bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
131861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13261f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
132776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
132876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
132976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
1331efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips            SkImageFilter::Proxy proxy(dstDev);
133276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
13336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1334b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1335fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1336d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
13374cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1338be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
133955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
13404cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
13415efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13425efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13436776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13446776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
134576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
134661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        } else if (deviceIsBitmapDevice) {
13479572a10c9a6a868bbb8f71d7806d0a45f183333freed            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
134861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
134976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1350b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
135176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
13570acf1b4b3645772d220c720313821bac389751b5reed    if (gTreatSpriteAsBitmap) {
13580acf1b4b3645772d220c720313821bac389751b5reed        this->save();
13590acf1b4b3645772d220c720313821bac389751b5reed        this->resetMatrix();
13600acf1b4b3645772d220c720313821bac389751b5reed        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
13610acf1b4b3645772d220c720313821bac389751b5reed        this->restore();
13620acf1b4b3645772d220c720313821bac389751b5reed        return;
13630acf1b4b3645772d220c720313821bac389751b5reed    }
13640acf1b4b3645772d220c720313821bac389751b5reed
13659881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
136650b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
13678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
13688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
136950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1370fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
13728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
13738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
13748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1375fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13768926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1377fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
13798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
13808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
13818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1383efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips            SkImageFilter::Proxy proxy(iter.fDevice);
13848926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
13856776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1386fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1387d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1388f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary            const SkIRect clipBounds = bitmap.bounds();
1389be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
139055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
13914cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
13925efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13935efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13946776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13955efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
13968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
13978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
13988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
13998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
14008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
14018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
14028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
14038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
140592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1406d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1407d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1408d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1412d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1413d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1414d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1418d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1419d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1420d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
142392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1424d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1425d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1426d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
142744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
142844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
142992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1430d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1431d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1432d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1433d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
14342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1436c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14371f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
143844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
143944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
144044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
144144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
144286a17e7716c8db858e219a46b9db3817bb770beereedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
144386a17e7716c8db858e219a46b9db3817bb770beereed    this->checkForDeferredSave();
14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1445c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14461f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
144744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
14524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1459759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
14602ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1466da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1467da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
14681f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1469da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1470da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1471da17f758442f16747af39f8fbaed9c097048519creed@google.com
14723b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1473da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1474c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1475da17f758442f16747af39f8fbaed9c097048519creed@google.com
1476687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
14771f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1478da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1479da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1480da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1481da17f758442f16747af39f8fbaed9c097048519creed@google.com
14825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1485c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14901f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1491123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
149298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
149398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
149498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14971f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
1498687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1499d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1501123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
150298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
150398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
150498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
15088f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
151273e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
151373e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1514d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1515819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1516819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1517759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
15182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15198f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
15218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
15228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
15244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
15258f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
152614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
15278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
152814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
15291f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
153014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
153114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
153214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
153314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
15348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
15358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
15368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
153714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1538687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
153914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
154014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
154114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
154214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
154373e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15448f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
154514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
154614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
154714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
154814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
154914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
15508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
15514ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
15524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1553759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
15542ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15558f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
15578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
15588f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
15598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
15618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1565da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1566da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
15671f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1568da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1569da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1570fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15713b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1572da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1573c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1574fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1575687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
15761f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1577da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1578da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1579da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1580da17f758442f16747af39f8fbaed9c097048519creed@google.com
15815c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1584c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15858f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
15868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
15878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
15901f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1592fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1593fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1594fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1595fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1596fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1597fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1598fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1599fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1600fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1601fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
16025c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1603687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
16045c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
160545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
16061a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
16071a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
16081a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
160945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
16101a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
161145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
161245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
161345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
161473e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
16158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1617759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
16182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16198f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
16235c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1626c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16285c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
16295c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1630687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
16315c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16321f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1635819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1636819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1637819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
16381f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1639ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
16405c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1641ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1642ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1643ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1644819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1645819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1646d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1647819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1648687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
16498182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
16508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
16518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
16528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
16538182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
16548182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
16558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16568182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
16578182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
16588182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16599cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
16609cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
16619cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
166273e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
16639cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
16649cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1665819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1666819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1667819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1668819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1669819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
167090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1671687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
16728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
16738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
16748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1675c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
167690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
167790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
167890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
16795c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
16805c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1681754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
16821f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1683754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1684754de5f65b466f721d952a379194cc94de376f42reed@google.com
16855c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
16861f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
16875c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16885c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16893b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
16901607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1691116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1692116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
16931f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16971f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1698a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
16991f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1700b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1701a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1702c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1703d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1704a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1705c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1706c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1707a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1708a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1709c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1710a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1711a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1712a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17163b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
17173b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17203b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1721bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
17228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1726d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1727d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
17281f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
172972dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
173072dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
173172dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1732d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1733d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1734d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
173549f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1736bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
17373b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
17383b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1739fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
17408f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
17418f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
17458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1747bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
17481f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1749bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1750bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1751bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1752bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1753bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1754bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1755bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
175649f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1757bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1758bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1759bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1760bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1761bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
17631f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17665c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
17671f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
17685c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17695c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17709c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
17719c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
17729c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
17739c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
17749c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1775644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1776644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1777644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
177849f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1779644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
178049f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1781644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1782644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1783644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1784644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1785644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1786644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1787644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1788644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1789e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1790ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1791ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
17929881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1793ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1794ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1795ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1796ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1797ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1798ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1799ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1800ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1801ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1802ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1803ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1804ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1805ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1806ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1807ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1808ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1809ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1810ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
181141af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
181241af966ab338e95eee81ab618ab28195075338f7reed
181341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
181441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
181541af966ab338e95eee81ab618ab28195075338f7reed}
181641af966ab338e95eee81ab618ab28195075338f7reed
181741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
181841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
181941af966ab338e95eee81ab618ab28195075338f7reed}
182041af966ab338e95eee81ab618ab28195075338f7reed
182141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
182241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
182341af966ab338e95eee81ab618ab28195075338f7reed}
182441af966ab338e95eee81ab618ab28195075338f7reed
182541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
182641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
182741af966ab338e95eee81ab618ab28195075338f7reed}
182841af966ab338e95eee81ab618ab28195075338f7reed
182941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
183041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
183141af966ab338e95eee81ab618ab28195075338f7reed}
183241af966ab338e95eee81ab618ab28195075338f7reed
183341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
183441af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
183541af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
183641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
183741af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
183841af966ab338e95eee81ab618ab28195075338f7reed}
183941af966ab338e95eee81ab618ab28195075338f7reed
184041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
184141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
184241af966ab338e95eee81ab618ab28195075338f7reed}
184341af966ab338e95eee81ab618ab28195075338f7reed
1844a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1845a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
184641af966ab338e95eee81ab618ab28195075338f7reed}
184741af966ab338e95eee81ab618ab28195075338f7reed
184841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1849a5517e2b190a8083b38964972b031c13e99f1012reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1850a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (dst.isEmpty()) {
1851a85d4d0814818e4ddabb9237da209d61d6cd5854reed        return;
1852a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
1853a5517e2b190a8083b38964972b031c13e99f1012reed    this->onDrawImageRect(image, src, dst, paint SRC_RECT_CONSTRAINT_ARG(constraint));
185441af966ab338e95eee81ab618ab28195075338f7reed}
185541af966ab338e95eee81ab618ab28195075338f7reed
18566fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
18576fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed                             const SkPaint* paint, SrcRectConstraint constraint) {
18586fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed    SkRect src = SkRect::Make(isrc);
18596fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed    this->drawImageRect(image, &src, dst, paint, constraint);
18606fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed}
18616fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed
18624c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
18634c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
18644c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
18654c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
18664c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
18674c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
18684c21dc5ddf3b482293ed34eead876d8d61a662c3reed        this->drawImageRect(image, NULL, dst, paint);
18694c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
18704c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->onDrawImageNine(image, center, dst, paint);
18714c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
18724c21dc5ddf3b482293ed34eead876d8d61a662c3reed
187341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
18744c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
18752df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18762df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
187741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
187841af966ab338e95eee81ab618ab28195075338f7reed}
187941af966ab338e95eee81ab618ab28195075338f7reed
18806fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed#ifdef SK_SUPPORT_LEGACY_DRAWBITMAPRECTFLAGS_TYPE
188141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
188241af966ab338e95eee81ab618ab28195075338f7reed                                    const SkPaint* paint, DrawBitmapRectFlags flags) {
18834c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
18842df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18852df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
1886a5517e2b190a8083b38964972b031c13e99f1012reed    this->onDrawBitmapRect(bitmap, src, dst, paint, (SK_VIRTUAL_CONSTRAINT_TYPE)flags);
1887a5517e2b190a8083b38964972b031c13e99f1012reed}
18886fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed#endif
1889a5517e2b190a8083b38964972b031c13e99f1012reed
1890a5517e2b190a8083b38964972b031c13e99f1012reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1891a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1892a5517e2b190a8083b38964972b031c13e99f1012reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
1893a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1894a5517e2b190a8083b38964972b031c13e99f1012reed    }
1895a5517e2b190a8083b38964972b031c13e99f1012reed    this->onDrawBitmapRect(bitmap, src, dst, paint, (SK_VIRTUAL_CONSTRAINT_TYPE)constraint);
189641af966ab338e95eee81ab618ab28195075338f7reed}
189741af966ab338e95eee81ab618ab28195075338f7reed
18986fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
18996fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed                              const SkPaint* paint, SrcRectConstraint constraint) {
19006fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed    SkRect src = SkRect::Make(isrc);
19016fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed    this->drawBitmapRect(bitmap, &src, dst, paint, constraint);
19026fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed}
19036fb0b6779e40ce05c20cf279f0ecff31fa3cd60dreed
190441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
190541af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
19064c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
19072df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19082df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
19094c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
1910a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
19114c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
191241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapNine(bitmap, center, dst, paint);
191341af966ab338e95eee81ab618ab28195075338f7reed}
191441af966ab338e95eee81ab618ab28195075338f7reed
191541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
19164c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
19172df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19182df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
191941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawSprite(bitmap, left, top, paint);
192041af966ab338e95eee81ab618ab28195075338f7reed}
192141af966ab338e95eee81ab618ab28195075338f7reed
192271c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
192371c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkColor colors[], int count, SkXfermode::Mode mode,
192471c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
192571c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
192671c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
192771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
192871c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(atlas);
192971c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(xform);
193071c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
193171c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
193271c3c760a83123ee0b3127b8c65c6394ce541c50reed}
193371c3c760a83123ee0b3127b8c65c6394ce541c50reed
19348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
193949f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
194028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
194128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
194228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
194328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
194441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
19459881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1946fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1947fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1948fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1949fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
1950c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, NULL, false)
19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
19548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
195941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
196041af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
19619881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
19638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
19648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
196778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1968a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1969a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1970a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1971a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1972a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1973a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1974a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
197578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
197678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1977a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1978a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1979fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1980a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
19818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
19844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
199241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
19939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
199478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
199578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
19978432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
19988432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
19998432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
20008432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
20018432808ad8898ac7137bc7ce1d9df6005e866401reed
20028432808ad8898ac7137bc7ce1d9df6005e866401reed        bounds = &paint.computeFastBounds(tmp, &storage);
200378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20074b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2008c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
20098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
201741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
20189881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
201978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
202078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
202278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
202378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
20254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
20264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2027306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
202878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
202946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
203046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
203146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
203246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
203346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
203446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
203741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
20389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
203978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
204078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
204278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
204378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20444ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
20454ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
20464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
20474ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20484ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
20494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
20504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2051f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2052f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
20534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2054f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2055f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
20564ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2057f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
205878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2059f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2060f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2061f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2062f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2063f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2064f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
20654ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20664ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2067ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2068ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
2069ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
2070ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
2071ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
2072ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
2073ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
2074ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
2075ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
2076ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
207725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2078ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
207925c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2080ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2081ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2082ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
208325c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2084ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2085ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
20864ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
208741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
20889881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
20899364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
20909364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
20919364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
20929364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
209378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
209478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
2095fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
209678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
209778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
209878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21020b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
21030b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
21040b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
21056803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2106fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
2107fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2108fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
2109fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
211178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2120a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
21219881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2122a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2123a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2124a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2125a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2126a85d4d0814818e4ddabb9237da209d61d6cd5854reed            paint->computeFastBounds(bounds, &bounds);
2127a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2128a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(bounds)) {
2129a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2130a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2131a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2132a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2133a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2134a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2135a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2136a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2137a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2138a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
2139a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2140a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2141a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImage(iter, image, x, y, looper.paint());
2142a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2143a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2144a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2145b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2146b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
214741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2148a5517e2b190a8083b38964972b031c13e99f1012reed                               const SkPaint* paint SRC_RECT_CONSTRAINT_PARAM(constraint)) {
21499881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2150a5517e2b190a8083b38964972b031c13e99f1012reed    SRC_RECT_CONSTRAINT_LOCAL_DEFAULT(constraint)
2151a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect storage;
2152a85d4d0814818e4ddabb9237da209d61d6cd5854reed    const SkRect* bounds = &dst;
2153a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2154a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2155a85d4d0814818e4ddabb9237da209d61d6cd5854reed            bounds = &paint->computeFastBounds(dst, &storage);
2156a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2157a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(*bounds)) {
2158a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2159a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2160a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2161a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2162a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2163a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2164a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2165a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2166c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, bounds,
2167c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
2168a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2169a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2170a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2171a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2172a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2173a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2174b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2175b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
217641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
21779881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
21798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21803d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
21819efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
21829efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
21839efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
21849efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
21859efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
21869efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
21879efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
21889efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
21893b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
21958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
21969bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21999987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
22007112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2201eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2202a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
220350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
220674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
220778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
220878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
22093d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
22109efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
22119efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
22129efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
22133b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
22143d60812865bb034851da777a91413ab584929887reed@google.com            return;
22153d60812865bb034851da777a91413ab584929887reed@google.com        }
22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22173d60812865bb034851da777a91413ab584929887reed@google.com
221833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
221933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
222033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22227064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2223c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, bounds,
2224c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
22257064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
222633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2227a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(),
2228a5517e2b190a8083b38964972b031c13e99f1012reed                                     (SK_VIRTUAL_CONSTRAINT_TYPE)constraint);
2229f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
22307064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
223133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
22328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
223441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2235a5517e2b190a8083b38964972b031c13e99f1012reed                                const SkPaint* paint, SK_VIRTUAL_CONSTRAINT_TYPE constraint) {
22369881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
22379987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2238a5517e2b190a8083b38964972b031c13e99f1012reed    this->internalDrawBitmapRect(bitmap, src, dst, paint, (SrcRectConstraint)constraint);
22399987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22409987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22414c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
22424c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
22434c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
22444c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22454c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkRect storage;
22464c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const SkRect* bounds = &dst;
22473d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
224860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
224960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
225060abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
22513b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
22523d60812865bb034851da777a91413ab584929887reed@google.com            return;
22533d60812865bb034851da777a91413ab584929887reed@google.com        }
22543d60812865bb034851da777a91413ab584929887reed@google.com    }
22554c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22564c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
22574c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (NULL == paint) {
22584c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
22594c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
22604c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22614c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
22624c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22634c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
22644c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
22659987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
22664c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22674c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
22689987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22699987ec3791336bad6af5cbe513564786b2df55aareed@google.com
227041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
227141af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
22729881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
22739987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
22749987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22754c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkRect storage;
22764c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const SkRect* bounds = &dst;
22774c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (NULL == paint || paint->canComputeFastBounds()) {
22784c21dc5ddf3b482293ed34eead876d8d61a662c3reed        if (paint) {
22794c21dc5ddf3b482293ed34eead876d8d61a662c3reed            bounds = &paint->computeFastBounds(dst, &storage);
22804c21dc5ddf3b482293ed34eead876d8d61a662c3reed        }
22814c21dc5ddf3b482293ed34eead876d8d61a662c3reed        if (this->quickReject(*bounds)) {
22824c21dc5ddf3b482293ed34eead876d8d61a662c3reed            return;
22834c21dc5ddf3b482293ed34eead876d8d61a662c3reed        }
22844c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
22854c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22864c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
22874c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (NULL == paint) {
22884c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
22894c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
22904c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22914c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
22924c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22934c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
22944c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
22954c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
22964c21dc5ddf3b482293ed34eead876d8d61a662c3reed
22974c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
22989987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22999987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2300f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2301f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
23021f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2303112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2304112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2305a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2306112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2307f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2308f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2309f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2310f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2311f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2312f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2313f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2314f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2315f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
23162c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
23172c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2318f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2319f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
232052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
232152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
232217b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
232352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
232452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
232552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
232617b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
232752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
232852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
232952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
233052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
233152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
233252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
233352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
233452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
233552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
233652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
233752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
233852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
233952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
234052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
234152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
234252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
234352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
234452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
234552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
234652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
234752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
234852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
234952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
235052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
235152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
235252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
235352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
235452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
235552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
235652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
235752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
235852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
235952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
236052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
236152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
236252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
236352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
236452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
236552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
236652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
236752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
236852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
236952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
237052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
237152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
237252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
237352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
237452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
237552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
237652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
237752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
237852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
237952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
238052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
238152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
238252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
238352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
238452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
238552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
238652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
238752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
238852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
238952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
239052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
239152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2392e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2393e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
239478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
23958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2398f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
239952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
240052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2406e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2407e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
240805c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
240905c4a4322e7d4f3417b7df33825bab8603d52051fmalita
241078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
241187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
241405c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2415f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2417b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2421e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2422e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
242305c4a4322e7d4f3417b7df33825bab8603d52051fmalita
242405c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
242505c4a4322e7d4f3417b7df33825bab8603d52051fmalita
242678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
242787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24294e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
243005c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2431f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2433b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2437e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2438e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
243978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
244087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
24434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
24448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2445b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2446945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
24474325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
24484325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
244900d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
245000d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
24517ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
245285d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
245385d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    const SkRect* bounds = NULL;
245419653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
245585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
245685d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        bounds = &paint.computeFastBounds(storage, &storage);
24577ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
245885d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        if (this->quickReject(*bounds)) {
24597ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita            return;
24607ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        }
24617ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
24627ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2463024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2464024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2465024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
2466024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = NULL;
2467024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
246885d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
246900d5c2c6523321d25b32905ff4822f083a4173eefmalita
2470aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2471aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2472024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
247300d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
247400d5c2c6523321d25b32905ff4822f083a4173eefmalita
2475aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2476024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2477024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
247800d5c2c6523321d25b32905ff4822f083a4173eefmalita}
247900d5c2c6523321d25b32905ff4822f083a4173eefmalita
2480e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2481e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2482e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
24839881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2484e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2485e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2486e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2487e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
24889881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2489e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2490e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2491e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2492e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
24939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2494e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2495e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2496e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2497e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
24989881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2499e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2500e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
250100d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
250200d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
25039881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
250449f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
250500d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
250600d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
250700d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2508e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
250941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
251041af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
251141af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
251241af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
251341af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
25149881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
251578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
25164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
25194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
25204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
25218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25224b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2526b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2527b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
25289881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2529b3c9d1c33caf325aada244204215eb790c228c12dandov    if (NULL == cubics) {
2530b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2531b3c9d1c33caf325aada244204215eb790c228c12dandov    }
25326cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2533ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2534ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2535ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2536b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2537ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2538ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2539ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
25406cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2541b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2542b3c9d1c33caf325aada244204215eb790c228c12dandov}
2543b3c9d1c33caf325aada244204215eb790c228c12dandov
2544b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2545b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2546b3c9d1c33caf325aada244204215eb790c228c12dandov
2547ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
25486cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2549ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2550b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2551ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
25526cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2553ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2554ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2555ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2556a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2557a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (dr) {
2558a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        if (x || y) {
2559a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2560a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            this->onDrawDrawable(dr, &matrix);
2561a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        } else {
2562a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            this->onDrawDrawable(dr, NULL);
2563a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        }
2564a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2565a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2566a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2567a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2568a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (dr) {
2569a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        if (matrix && matrix->isIdentity()) {
2570a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            matrix = NULL;
2571a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        }
2572a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        this->onDrawDrawable(dr, matrix);
25736a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
25746a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
25756a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2576a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2577a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    SkRect bounds = dr->getBounds();
2578a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (matrix) {
2579a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        matrix->mapRect(&bounds);
2580a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2581a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (this->quickReject(bounds)) {
2582a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        return;
2583a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2584a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
25856a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
25866a070dc06af4e9f305f9d08a69e34d18ade473cbreed
258771c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
258871c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkColor colors[], int count, SkXfermode::Mode mode,
258971c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
259071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
259171c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
259271c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
259371c3c760a83123ee0b3127b8c65c6394ce541c50reed
259471c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
259571c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
259671c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
259771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
259871c3c760a83123ee0b3127b8c65c6394ce541c50reed
259971c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, NULL)
260071c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
260171c3c760a83123ee0b3127b8c65c6394ce541c50reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
260271c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
260371c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
260471c3c760a83123ee0b3127b8c65c6394ce541c50reed}
260571c3c760a83123ee0b3127b8c65c6394ce541c50reed
26068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
26088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
26098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2612845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
26139881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
26148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2617845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
26180baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
26198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
26218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2623845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
26249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
26258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2628845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
26290baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
26308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
26328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
26359881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
26368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
26374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
26398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
26408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
26439881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
26448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
26458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
26488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
26498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
26508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
26538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
26549881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
26558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
26564b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
26588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
26598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
26608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
26638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
26648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
26659881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
26668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
26678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
26698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
26708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
26738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
26749881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
26758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
26768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
26778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
26808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
26814ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
26828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
26858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
26869881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
26878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
26888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
26898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
26903b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
26918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
26928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
26938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
26944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
26954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
26964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
26978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
26988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
26998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
27038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
27048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
27059881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
27068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
27078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
27088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
27108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
27128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
27148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
27158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
27168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
27188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
27228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
27249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
27258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
27264b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
27288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
27298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2731f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
27321c2c441fede0ae9573afc098017011e3439624a9reed
27331c2c441fede0ae9573afc098017011e3439624a9reed/**
27341c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
27351c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
27361c2c441fede0ae9573afc098017011e3439624a9reed *
27371c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
27381c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
27391c2c441fede0ae9573afc098017011e3439624a9reed */
27401c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
27419b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2742d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
27431c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
274449f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2745d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
2746d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            matrix = NULL;
2747d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
27481c2c441fede0ae9573afc098017011e3439624a9reed        if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
27491c2c441fede0ae9573afc098017011e3439624a9reed            SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
27501c2c441fede0ae9573afc098017011e3439624a9reed            picture->playback(this);
27511c2c441fede0ae9573afc098017011e3439624a9reed        } else {
27521c2c441fede0ae9573afc098017011e3439624a9reed            this->onDrawPicture(picture, matrix, paint);
27531c2c441fede0ae9573afc098017011e3439624a9reed        }
2754d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2755d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
27569b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2757d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2758d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2759145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
276049f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2761145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2762145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2763d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2764145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2765145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2766145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2767145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2768a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2769c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
27738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
27748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2776d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
27778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
27798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
27818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
27828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
27858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
27868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
27898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
27908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27921f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
27938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
27948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
27978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
27988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
28018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
28028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
28038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
28048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
28068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
28098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
28108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
281120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
281220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
281320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2814c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
28153107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28163107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
28173107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28183107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
28193107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
28203107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
28213107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
28223107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28233107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28243107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28253107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28263107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28273107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
28283107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
28293107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
283028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
28313107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28323107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28333107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28343107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28353107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28363107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
28373107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
28383107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
283942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
284042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
284142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
284242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2843eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
284442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
284542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
284642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
284742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
284842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
284942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2850d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2851d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2852d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2853d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2854a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2855d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2856d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2857d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
285849f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2859a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2860d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2861a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2862d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2863a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
286449f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2865d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2866d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
28676cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
286849f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2869d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2870d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2871d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2872d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2873d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2874d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2875d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2876