PictureRenderer.cpp revision 9c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254
1b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org/*
2b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * Copyright 2012 Google Inc.
3b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org *
4b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * Use of this source code is governed by a BSD-style license that can be
5b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * found in the LICENSE file.
6b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org */
7b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org
8451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "PictureRenderer.h"
958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "picture_utils.h"
10451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SamplePipeControllers.h"
11451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkCanvas.h"
12451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkDevice.h"
13451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkGPipe.h"
1458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#if SK_SUPPORT_GPU
1558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkGpuDevice.h"
1658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#endif
1758b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkGraphics.h"
1858b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkImageEncoder.h"
19a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com#include "SkMaskFilter.h"
20ea82695325e2afc68f646fcc23fcae8b1bff6dc1keyar@chromium.org#include "SkMatrix.h"
21451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkPicture.h"
229313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org#include "SkRTree.h"
23ea82695325e2afc68f646fcc23fcae8b1bff6dc1keyar@chromium.org#include "SkScalar.h"
24a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com#include "SkStream.h"
259299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org#include "SkString.h"
2658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkTemplates.h"
273cb834bd27a16cc60ff30adae96659558c2dc91fjunov@chromium.org#include "SkTileGridPicture.h"
28451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkTDArray.h"
2958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkThreadUtils.h"
30451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkTypes.h"
31fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkData.h"
32fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkPictureUtils.h"
334ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org
34451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgnamespace sk_tools {
35451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
36451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgenum {
37451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    kDefaultTileWidth = 256,
38451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    kDefaultTileHeight = 256
39451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org};
40451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
419d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid PictureRenderer::init(SkPicture* pict) {
4278a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    SkASSERT(NULL == fPicture);
4378a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    SkASSERT(NULL == fCanvas.get());
4478a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (fPicture != NULL || NULL != fCanvas.get()) {
459d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
469d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
479d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
489d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(pict != NULL);
4978a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == pict) {
509d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
519d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
529d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
539d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    fPicture = pict;
549313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    fPicture->ref();
55a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org    fCanvas.reset(this->setupCanvas());
56a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org}
57a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
58a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comclass FlagsDrawFilter : public SkDrawFilter {
59a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.compublic:
60a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) :
61a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        fFlags(flags) {}
62a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
63971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com    virtual bool filter(SkPaint* paint, Type t) {
64a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags);
65457d8a77bed0160519fc5dfb67d0e02f9c3950a2reed@google.com        if (PictureRenderer::kBlur_DrawFilterFlag & fFlags[t]) {
66a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            SkMaskFilter* maskFilter = paint->getMaskFilter();
67a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            SkMaskFilter::BlurInfo blurInfo;
68a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            if (maskFilter && maskFilter->asABlur(&blurInfo)) {
69457d8a77bed0160519fc5dfb67d0e02f9c3950a2reed@google.com                paint->setMaskFilter(NULL);
70a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            }
71a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        }
72a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) {
73a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            paint->setHinting(SkPaint::kNo_Hinting);
74a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) {
75a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            paint->setHinting(SkPaint::kSlight_Hinting);
76a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        }
77971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        return true;
78a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    }
79a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
80a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comprivate:
81a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    PictureRenderer::DrawFilterFlags* fFlags;
82a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com};
83a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
8482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comstatic void setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) {
85a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    if (drawFilters && !canvas->getDrawFilter()) {
86a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref();
87e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com        if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) {
88e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com            canvas->setAllowSoftClip(false);
89e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com        }
90a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    }
91a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com}
92a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
93a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas() {
94c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
95c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
96c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return this->setupCanvas(width, height);
97a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org}
98a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
99a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas(int width, int height) {
100a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    SkCanvas* canvas;
1014ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org    switch(fDeviceType) {
1024ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        case kBitmap_DeviceType: {
1034ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkBitmap bitmap;
104a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org            sk_tools::setup_bitmap(&bitmap, width, height);
105a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            canvas = SkNEW_ARGS(SkCanvas, (bitmap));
1064ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        }
10782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        break;
1084ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#if SK_SUPPORT_GPU
1094ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        case kGPU_DeviceType: {
1104ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
1110612564bb76ec533d26d87e03368fd81ef97831ekeyar@chromium.org                                                    (fGrContext, SkBitmap::kARGB_8888_Config,
112a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org                                                    width, height)));
113a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            canvas = SkNEW_ARGS(SkCanvas, (device.get()));
1144ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        }
11582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        break;
1164ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#endif
1174ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        default:
1184ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkASSERT(0);
11982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com            return NULL;
1204ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org    }
12182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    setUpFilter(canvas, fDrawFilters);
12282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    this->scaleToScaleFactor(canvas);
12382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    return canvas;
12482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com}
125a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
12682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comvoid PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) {
12782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkASSERT(canvas != NULL);
12882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    if (fScaleFactor != SK_Scalar1) {
12982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        canvas->scale(fScaleFactor, fScaleFactor);
13082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    }
1319d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org}
1329d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
1339d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid PictureRenderer::end() {
13477a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org    this->resetState();
1359313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkSafeUnref(fPicture);
1369d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    fPicture = NULL;
1379d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    fCanvas.reset(NULL);
1389d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org}
1399d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
140c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewWidth() {
141c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    SkASSERT(fPicture != NULL);
142c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    int width = fPicture->width();
143c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (fViewport.width() > 0) {
144c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        width = SkMin32(width, fViewport.width());
145c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    }
146c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return width;
147c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com}
148c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
149c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewHeight() {
150c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    SkASSERT(fPicture != NULL);
151c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    int height = fPicture->height();
152c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (fViewport.height() > 0) {
153c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        height = SkMin32(height, fViewport.height());
154c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    }
155c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return height;
156c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com}
157c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
1589313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org/** Converts fPicture to a picture that uses a BBoxHierarchy.
1599313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org *  PictureRenderer subclasses that are used to test picture playback
1609313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org *  should call this method during init.
1619313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org */
1629313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgvoid PictureRenderer::buildBBoxHierarchy() {
1639313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkASSERT(NULL != fPicture);
1649313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) {
1659313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        SkPicture* newPicture = this->createPicture();
1669313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(),
1679313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org                                                        this->recordFlags());
1689313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        fPicture->draw(recorder);
1699313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        newPicture->endRecording();
1709313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        fPicture->unref();
1719313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        fPicture = newPicture;
1729313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
1739313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
1749313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
17577a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.orgvoid PictureRenderer::resetState() {
17628136b308fe467da113983cfee332faea133cd8akeyar@chromium.org#if SK_SUPPORT_GPU
17728136b308fe467da113983cfee332faea133cd8akeyar@chromium.org    if (this->isUsingGpuDevice()) {
17828136b308fe467da113983cfee332faea133cd8akeyar@chromium.org        SkGLContext* glContext = fGrContextFactory.getGLContext(
17928136b308fe467da113983cfee332faea133cd8akeyar@chromium.org            GrContextFactory::kNative_GLContextType);
18028136b308fe467da113983cfee332faea133cd8akeyar@chromium.org
18128136b308fe467da113983cfee332faea133cd8akeyar@chromium.org        SkASSERT(glContext != NULL);
18228136b308fe467da113983cfee332faea133cd8akeyar@chromium.org        if (NULL == glContext) {
18328136b308fe467da113983cfee332faea133cd8akeyar@chromium.org            return;
18428136b308fe467da113983cfee332faea133cd8akeyar@chromium.org        }
18528136b308fe467da113983cfee332faea133cd8akeyar@chromium.org
1869a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com        fGrContext->flush();
18777a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org        SK_GL(*glContext, Finish());
18877a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org    }
189a40c20df0e4c5d04acb0841d70127778c0a779eckeyar@chromium.org#endif
19077a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org}
19177a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org
1929313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orguint32_t PictureRenderer::recordFlags() {
1939313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    return kNone_BBoxHierarchyType == fBBoxHierarchyType ? 0 :
1949313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        SkPicture::kOptimizeForClippedPlayback_RecordingFlag;
1959313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
1969313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
197b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com/**
198b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * Write the canvas to the specified path.
199b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @param canvas Must be non-null. Canvas to be written to a file.
200b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @param path Path for the file to be written. Should have no extension; write() will append
201b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com *             an appropriate one. Passed in by value so it can be modified.
202b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @return bool True if the Canvas is written to a file.
203b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com */
204b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.comstatic bool write(SkCanvas* canvas, SkString path) {
20581f9d2e05be4902993345dac93337158345c660bscroggo@google.com    SkASSERT(canvas != NULL);
206b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    if (NULL == canvas) {
2079299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org        return false;
2089299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    }
2099299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
2109299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    SkBitmap bitmap;
21181f9d2e05be4902993345dac93337158345c660bscroggo@google.com    SkISize size = canvas->getDeviceSize();
21281f9d2e05be4902993345dac93337158345c660bscroggo@google.com    sk_tools::setup_bitmap(&bitmap, size.width(), size.height());
2139299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
21481f9d2e05be4902993345dac93337158345c660bscroggo@google.com    canvas->readPixels(&bitmap, 0, 0);
2159299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    sk_tools::force_all_opaque(bitmap);
2169299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
21781f9d2e05be4902993345dac93337158345c660bscroggo@google.com    // Since path is passed in by value, it is okay to modify it.
21881f9d2e05be4902993345dac93337158345c660bscroggo@google.com    path.append(".png");
2199299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
2209299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org}
2219299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
222b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com/**
223b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * If path is non NULL, append number to it, and call write(SkCanvas*, SkString) to write the
224b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * provided canvas to a file. Returns true if path is NULL or if write() succeeds.
225b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com */
226b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.comstatic bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number) {
227b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    if (NULL == path) {
228b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com        return true;
229b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    }
230b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    SkString pathWithNumber(*path);
231b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    pathWithNumber.appendf("%i", number);
232b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    return write(canvas, pathWithNumber);
233b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com}
234b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com
235acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
236acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
237fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.comSkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
238fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com    // defer the canvas setup until the render step
239fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com    return NULL;
240fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com}
241fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com
242a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.comstatic bool PNGEncodeBitmapToStream(SkWStream* wStream, const SkBitmap& bm) {
243a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com    return SkImageEncoder::EncodeStream(wStream, bm, SkImageEncoder::kPNG_Type, 100);
244a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com}
245a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com
24684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool RecordPictureRenderer::render(const SkString* path, SkBitmap** out) {
2479313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkAutoTUnref<SkPicture> replayer(this->createPicture());
24882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->getViewHeight(),
2499313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org                                                  this->recordFlags());
25082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    this->scaleToScaleFactor(recorder);
2519a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fPicture->draw(recorder);
2529313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    replayer->endRecording();
253a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com    if (path != NULL) {
254a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        // Record the new picture as a new SKP with PNG encoded bitmaps.
255a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        SkString skpPath(*path);
256a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        // ".skp" was removed from 'path' before being passed in here.
257a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        skpPath.append(".skp");
258a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        SkFILEWStream stream(skpPath.c_str());
259a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        replayer->serialize(&stream, &PNGEncodeBitmapToStream);
260a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        return true;
261a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com    }
26281f9d2e05be4902993345dac93337158345c660bscroggo@google.com    return false;
2639a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com}
2649a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
2650a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString RecordPictureRenderer::getConfigNameInternal() {
2660a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("record");
2670a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
2680a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
269acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
270acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
27184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool PipePictureRenderer::render(const SkString* path, SkBitmap** out) {
2729d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fCanvas.get() != NULL);
2739d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fPicture != NULL);
27478a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == fCanvas.get() || NULL == fPicture) {
27581f9d2e05be4902993345dac93337158345c660bscroggo@google.com        return false;
2769d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
2779d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
2789d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    PipeController pipeController(fCanvas.get());
279451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    SkGPipeWriter writer;
280451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
2819d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    pipeCanvas->drawPicture(*fPicture);
282451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    writer.endRecording();
2839a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fCanvas->flush();
284070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com    if (NULL != path) {
285070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com        return write(fCanvas, *path);
286070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com    }
28784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (NULL != out) {
28884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
28984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
29084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fCanvas->readPixels(*out, 0, 0);
291a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com    }
292070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com    return true;
293451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
294451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
2950a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PipePictureRenderer::getConfigNameInternal() {
2960a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("pipe");
2970a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
2980a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
299acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
300acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
3019313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgvoid SimplePictureRenderer::init(SkPicture* picture) {
3029313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    INHERITED::init(picture);
3039313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    this->buildBBoxHierarchy();
3049313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
3059313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
30684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool SimplePictureRenderer::render(const SkString* path, SkBitmap** out) {
3079d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fCanvas.get() != NULL);
3089d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fPicture != NULL);
30978a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == fCanvas.get() || NULL == fPicture) {
31081f9d2e05be4902993345dac93337158345c660bscroggo@google.com        return false;
3119d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
3129d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
3139d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    fCanvas->drawPicture(*fPicture);
3149a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fCanvas->flush();
315070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com    if (NULL != path) {
316070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com        return write(fCanvas, *path);
317070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com    }
318a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com
31984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (NULL != out) {
32084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
32184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
32284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fCanvas->readPixels(*out, 0, 0);
32384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
32484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
325070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com    return true;
326451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
327451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
3280a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString SimplePictureRenderer::getConfigNameInternal() {
3290a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("simple");
3300a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
3310a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
332acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
333acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
334451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgTiledPictureRenderer::TiledPictureRenderer()
335a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    : fTileWidth(kDefaultTileWidth)
336b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com    , fTileHeight(kDefaultTileHeight)
337a04dc02b118363fedf3a7b11cfcdab886d368f8arileya@google.com    , fTileWidthPercentage(0.0)
338b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com    , fTileHeightPercentage(0.0)
339cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTileMinPowerOf2Width(0)
340cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fCurrentTileOffset(-1)
341cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTilesX(0)
342cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTilesY(0) { }
343451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
3449d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::init(SkPicture* pict) {
3459d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(pict != NULL);
346acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    SkASSERT(0 == fTileRects.count());
347acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    if (NULL == pict || fTileRects.count() != 0) {
3489d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
3499d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
3509d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
351acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not
352acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    // used by bench_pictures.
353acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    fPicture = pict;
3549313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    fPicture->ref();
355a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    this->buildBBoxHierarchy();
356cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org
357cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    if (fTileWidthPercentage > 0) {
3585d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
359cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    }
360cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    if (fTileHeightPercentage > 0) {
3615d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
362cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    }
363cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org
364f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    if (fTileMinPowerOf2Width > 0) {
365f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        this->setupPowerOf2Tiles();
366f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    } else {
367f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        this->setupTiles();
368f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
369cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight));
370cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    // Initialize to -1 so that the first call to nextTile will set this up to draw tile 0 on the
371cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    // first call to drawCurrentTile.
372cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fCurrentTileOffset = -1;
373451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
374451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
3759d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::end() {
376bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    fTileRects.reset();
3779d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    this->INHERITED::end();
378451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
379451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
3809d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::setupTiles() {
381c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    // Only use enough tiles to cover the viewport
382c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
383c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
384c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
385cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fTilesX = fTilesY = 0;
386c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
387cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        fTilesY++;
388c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWidth) {
389cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            if (0 == tile_y_start) {
390cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                // Only count tiles in the X direction on the first pass.
391cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                fTilesX++;
392cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            }
393acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com            *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
394acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(tile_y_start),
395acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(fTileWidth),
396acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(fTileHeight));
397f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        }
398f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
399f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org}
400f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
401cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::tileDimensions(int &x, int &y) {
402cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    if (fTileRects.count() == 0 || NULL == fPicture) {
403cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        return false;
404cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    }
405cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    x = fTilesX;
406cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    y = fTilesY;
407cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    return true;
408cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
409cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
410f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// The goal of the powers of two tiles is to minimize the amount of wasted tile
411f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// space in the width-wise direction and then minimize the number of tiles. The
412f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// constraints are that every tile must have a pixel width that is a power of
413f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// two and also be of some minimal width (that is also a power of two).
414f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org//
41558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com// This is solved by first taking our picture size and rounding it up to the
416f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// multiple of the minimal width. The binary representation of this rounded
417f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// value gives us the tiles we need: a bit of value one means we need a tile of
418f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// that size.
419f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.orgvoid TiledPictureRenderer::setupPowerOf2Tiles() {
420c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    // Only use enough tiles to cover the viewport
421c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
422c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
423c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
424c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    int rounded_value = width;
425c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (width % fTileMinPowerOf2Width != 0) {
426c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerOf2Width;
427f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
428f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
429c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    int num_bits = SkScalarCeilToInt(SkScalarLog2(SkIntToScalar(width)));
430f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    int largest_possible_tile_size = 1 << num_bits;
431f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
432cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fTilesX = fTilesY = 0;
433f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    // The tile height is constant for a particular picture.
434c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
435cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        fTilesY++;
436f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        int tile_x_start = 0;
437f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        int current_width = largest_possible_tile_size;
438acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough
439acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        // to draw each tile.
440acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        fTileWidth = current_width;
441f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
442f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        while (current_width >= fTileMinPowerOf2Width) {
443f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            // It is very important this is a bitwise AND.
444f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            if (current_width & rounded_value) {
445cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                if (0 == tile_y_start) {
446cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                    // Only count tiles in the X direction on the first pass.
447cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                    fTilesX++;
448cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                }
449acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
450acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(tile_y_start),
451acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(current_width),
452acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(fTileHeight));
453f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org                tile_x_start += current_width;
454f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            }
455f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
456f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            current_width >>= 1;
457451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org        }
458451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    }
459451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
460451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
461bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com/**
462bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * Draw the specified playback to the canvas translated to rectangle provided, so that this mini
463bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * canvas represents the rectangle's portion of the overall picture.
464bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * Saves and restores so that the initial clip and matrix return to their state before this function
465bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * is called.
466bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com */
467bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.comtemplate<class T>
468bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.comstatic void DrawTileToCanvas(SkCanvas* canvas, const SkRect& tileRect, T* playback) {
469bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    int saveCount = canvas->save();
47082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Translate so that we draw the correct portion of the picture.
47182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Perform a postTranslate so that the scaleFactor does not interfere with the positioning.
47282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkMatrix mat(canvas->getTotalMatrix());
47382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    mat.postTranslate(-tileRect.fLeft, -tileRect.fTop);
47482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    canvas->setMatrix(mat);
475bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    playback->draw(canvas);
476bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    canvas->restoreToCount(saveCount);
477bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    canvas->flush();
478451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
479451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
48058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
481bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
48284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.comstatic void bitmapCopySubset(const SkBitmap& src, SkBitmap* dst, int xDst,
48384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                             int yDst) {
48484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    for (int y = 0; y <src.height() && y + yDst < dst->height() ; y++) {
48584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        for (int x = 0; x < src.width() && x + xDst < dst->width() ; x++) {
48684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            *dst->getAddr32(xDst + x, yDst + y) = *src.getAddr32(x, y);
48784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
48884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
48984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com}
49084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
491cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::nextTile(int &i, int &j) {
492cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    if (++fCurrentTileOffset < fTileRects.count()) {
493cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        i = fCurrentTileOffset % fTilesX;
494cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        j = fCurrentTileOffset / fTilesX;
495cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        return true;
496cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    }
497cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    return false;
498cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
499cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
500cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.comvoid TiledPictureRenderer::drawCurrentTile() {
501cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count());
502cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    DrawTileToCanvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture);
503cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
504cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
50584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool TiledPictureRenderer::render(const SkString* path, SkBitmap** out) {
506a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkASSERT(fPicture != NULL);
507a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    if (NULL == fPicture) {
508a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        return false;
509bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
510bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
51184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    SkBitmap bitmap;
51284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (out){
51384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
51484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
51584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(&bitmap, fTileWidth, fTileHeight);
51684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
517a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool success = true;
518a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fTileRects.count(); ++i) {
519cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        DrawTileToCanvas(fCanvas, fTileRects[i], fPicture);
520a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        if (NULL != path) {
521cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            success &= writeAppendNumber(fCanvas, path, i);
522b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com        }
52384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        if (NULL != out) {
52484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            if (fCanvas->readPixels(&bitmap, 0, 0)) {
5259c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com                bitmapCopySubset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()),
5269c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com                                 SkScalarFloorToInt(fTileRects[i].top()));
52784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            } else {
52884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                success = false;
52984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            }
53084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
531bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
532a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return success;
533bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
53458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
535a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comSkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) {
536a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkCanvas* canvas = this->INHERITED::setupCanvas(width, height);
537a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkASSERT(fPicture != NULL);
53882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This
53982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // is mostly important for tiles on the right and bottom edges as they may go over this area and
54082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // the picture may have some commands that draw outside of this area and so should not actually
54182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // be written.
54282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Uses a clipRegion so that it will be unaffected by the scale factor, which may have been set
54382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // by INHERITED::setupCanvas.
54482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkRegion clipRegion;
54582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight());
54682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    canvas->clipRegion(clipRegion);
547a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return canvas;
548a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
5490a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
5500a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString TiledPictureRenderer::getConfigNameInternal() {
5510a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    SkString name;
5520a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    if (fTileMinPowerOf2Width > 0) {
5530a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.append("pow2tile_");
5540a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%i", fTileMinPowerOf2Width);
5550a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    } else {
5560a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.append("tile_");
5570a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        if (fTileWidthPercentage > 0) {
5580a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com            name.appendf("%.f%%", fTileWidthPercentage);
5590a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        } else {
5600a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com            name.appendf("%i", fTileWidth);
5610a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        }
5620a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    }
5630a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    name.append("x");
5640a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    if (fTileHeightPercentage > 0) {
5650a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%.f%%", fTileHeightPercentage);
5660a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    } else {
5670a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%i", fTileHeight);
5680a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    }
5690a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return name;
5700a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
5710a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
57258b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
57358b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
574a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com// Holds all of the information needed to draw a set of tiles.
575a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comclass CloneData : public SkRunnable {
576a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
577a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.compublic:
578a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end,
579a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com              SkRunnable* done)
580a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        : fClone(clone)
581a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fCanvas(canvas)
582a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fPath(NULL)
583a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fRects(rects)
584a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fStart(start)
585a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fEnd(end)
586a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fSuccess(NULL)
587a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fDone(done) {
588a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkASSERT(fDone != NULL);
589a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
590a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
591a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    virtual void run() SK_OVERRIDE {
592a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkGraphics::SetTLSFontCacheLimit(1024 * 1024);
59384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
59484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        SkBitmap bitmap;
59584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        if (fBitmap != NULL) {
59684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            // All tiles are the same size.
5979c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com            setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScalarFloorToInt(fRects[0].height()));
59884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
599a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com
600a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        for (int i = fStart; i < fEnd; i++) {
601a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            DrawTileToCanvas(fCanvas, fRects[i], fClone);
602a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            if (fPath != NULL && !writeAppendNumber(fCanvas, fPath, i)
603a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                && fSuccess != NULL) {
604a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                *fSuccess = false;
605a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                // If one tile fails to write to a file, do not continue drawing the rest.
606a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                break;
607a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            }
60884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            if (fBitmap != NULL) {
60984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                if (fCanvas->readPixels(&bitmap, 0, 0)) {
61084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                    SkAutoLockPixels alp(*fBitmap);
6119c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com                    bitmapCopySubset(bitmap, fBitmap, SkScalarFloorToInt(fRects[i].left()),
6129c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com                                     SkScalarFloorToInt(fRects[i].top()));
61384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                } else {
61484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                    *fSuccess = false;
61584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                    // If one tile fails to read pixels, do not continue drawing the rest.
61684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                    break;
61784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                }
61884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            }
619a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        }
620a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fDone->run();
621a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
622bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
623a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    void setPathAndSuccess(const SkString* path, bool* success) {
624a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fPath = path;
625a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fSuccess = success;
626a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
627bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
62884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    void setBitmap(SkBitmap* bitmap) {
62984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fBitmap = bitmap;
63084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
63184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
632a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comprivate:
633a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // All pointers unowned.
634a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkPicture*         fClone;      // Picture to draw from. Each CloneData has a unique one which
635a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                                    // is threadsafe.
636a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkCanvas*          fCanvas;     // Canvas to draw to. Reused for each tile.
637a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const SkString*    fPath;       // If non-null, path to write the result to as a PNG.
638a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkTDArray<SkRect>& fRects;      // All tiles of the picture.
639a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const int          fStart;      // Range of tiles drawn by this thread.
640a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const int          fEnd;
641a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool*              fSuccess;    // Only meaningful if path is non-null. Shared by all threads,
642a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                                    // and only set to false upon failure to write to a PNG.
643a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkRunnable*        fDone;
64484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    SkBitmap*          fBitmap;
64558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com};
64658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
647a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comMultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount)
648a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com: fNumThreads(threadCount)
649a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com, fThreadPool(threadCount)
650a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com, fCountdown(threadCount) {
651a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Only need to create fNumThreads - 1 clones, since one thread will use the base
652a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // picture.
653a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1);
654a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads);
655a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
656a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
657a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comvoid MultiCorePictureRenderer::init(SkPicture *pict) {
658a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Set fPicture and the tiles.
659a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    this->INHERITED::init(pict);
660a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads; ++i) {
661a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->getTileHeight());
662a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
663a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Only need to create fNumThreads - 1 clones, since one thread will use the base picture.
664a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fPicture->clone(fPictureClones, fNumThreads - 1);
665a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Populate each thread with the appropriate data.
666a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all.
667a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads;
668a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
669a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads; i++) {
670a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkPicture* pic;
671a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        if (i == fNumThreads-1) {
672a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            // The last set will use the original SkPicture.
673a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            pic = fPicture;
674a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        } else {
675a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            pic = &fPictureClones[i];
676b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com        }
677a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        const int start = i * chunkSize;
678a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        const int end = SkMin32(start + chunkSize, fTileRects.count());
679a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fCloneData[i] = SkNEW_ARGS(CloneData,
680a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                                   (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown));
681bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
682bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
68358b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
68484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool MultiCorePictureRenderer::render(const SkString *path, SkBitmap** out) {
685a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool success = true;
686a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    if (path != NULL) {
687a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        for (int i = 0; i < fNumThreads-1; i++) {
688a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            fCloneData[i]->setPathAndSuccess(path, &success);
689bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com        }
690bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
691bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
69284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (NULL != out) {
69384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
69484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
69584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        for (int i = 0; i < fNumThreads; i++) {
69684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            fCloneData[i]->setBitmap(*out);
69784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
69884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    } else {
69984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        for (int i = 0; i < fNumThreads; i++) {
70084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            fCloneData[i]->setBitmap(NULL);
70184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
70284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
70384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
704a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCountdown.reset(fNumThreads);
705a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads; i++) {
706a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fThreadPool.add(fCloneData[i]);
707acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    }
708a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCountdown.wait();
709acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
710a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return success;
711a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
712a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
713a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comvoid MultiCorePictureRenderer::end() {
714a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads - 1; i++) {
715a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkDELETE(fCloneData[i]);
716a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fCloneData[i] = NULL;
717163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org    }
718a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
719a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCanvasPool.unrefAll();
720a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
721a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    this->INHERITED::end();
722163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org}
723163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org
724a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comMultiCorePictureRenderer::~MultiCorePictureRenderer() {
725a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Each individual CloneData was deleted in end.
726a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkDELETE_ARRAY(fCloneData);
727a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkDELETE_ARRAY(fPictureClones);
728bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
729bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
7300a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString MultiCorePictureRenderer::getConfigNameInternal() {
7310a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    SkString name = this->INHERITED::getConfigNameInternal();
7320a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    name.appendf("_multi_%i_threads", fNumThreads);
7330a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return name;
7340a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
7350a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
736acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
7379a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
7389a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.comvoid PlaybackCreationRenderer::setup() {
7399313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    fReplayer.reset(this->createPicture());
74082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkCanvas* recorder = fReplayer->beginRecording(this->getViewWidth(), this->getViewHeight(),
7419313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org                                                   this->recordFlags());
74282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    this->scaleToScaleFactor(recorder);
7439a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fPicture->draw(recorder);
7449a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com}
7459a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
74684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool PlaybackCreationRenderer::render(const SkString*, SkBitmap** out) {
7479313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    fReplayer->endRecording();
74881f9d2e05be4902993345dac93337158345c660bscroggo@google.com    // Since this class does not actually render, return false.
74981f9d2e05be4902993345dac93337158345c660bscroggo@google.com    return false;
750451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
751451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
7520a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PlaybackCreationRenderer::getConfigNameInternal() {
7530a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("playback_creation");
7540a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
7550a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
7569313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org///////////////////////////////////////////////////////////////////////////////////////////////
7579313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org// SkPicture variants for each BBoxHierarchy type
7589313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
7599313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgclass RTreePicture : public SkPicture {
7609313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgpublic:
7619313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{
7629313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        static const int kRTreeMinChildren = 6;
7639313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        static const int kRTreeMaxChildren = 11;
7649313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
7659313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org                                           SkIntToScalar(fHeight));
7669313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
7679313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org                               aspectRatio);
7689313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
7699313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org};
7709313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
7719313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgSkPicture* PictureRenderer::createPicture() {
7729313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    switch (fBBoxHierarchyType) {
7739313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        case kNone_BBoxHierarchyType:
7749313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org            return SkNEW(SkPicture);
7759313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        case kRTree_BBoxHierarchyType:
7769313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org            return SkNEW(RTreePicture);
7777b53706a7d596a2d8dce6cfe5b543264e5a37239junov@chromium.org        case kTileGrid_BBoxHierarchyType:
7783cb834bd27a16cc60ff30adae96659558c2dc91fjunov@chromium.org            return SkNEW_ARGS(SkTileGridPicture, (fGridWidth, fGridHeight, fPicture->width(),
7793cb834bd27a16cc60ff30adae96659558c2dc91fjunov@chromium.org                fPicture->height()));
7809313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
7819313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkASSERT(0); // invalid bbhType
7829313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    return NULL;
783451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
7849313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
785fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com///////////////////////////////////////////////////////////////////////////////
786fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
787fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comclass GatherRenderer : public PictureRenderer {
788fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.compublic:
78984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    virtual bool render(const SkString* path, SkBitmap** out = NULL)
79084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            SK_OVERRIDE {
791fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
792fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                                       SkIntToScalar(fPicture->height()));
793fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
794fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkSafeUnref(data);
795c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
796fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        return NULL == path;    // we don't have anything to write
797fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
798c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
799fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comprivate:
800fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual SkString getConfigNameInternal() SK_OVERRIDE {
801fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        return SkString("gather_pixelrefs");
802fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
803fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com};
804fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
805fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comPictureRenderer* CreateGatherPixelRefsRenderer() {
806fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    return SkNEW(GatherRenderer);
807fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com}
808c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com
8095a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com///////////////////////////////////////////////////////////////////////////////
8105a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com
8115a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comclass PictureCloneRenderer : public PictureRenderer {
8125a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.compublic:
81384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    virtual bool render(const SkString* path, SkBitmap** out = NULL)
81484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            SK_OVERRIDE {
8155a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        for (int i = 0; i < 100; ++i) {
8165a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com            SkPicture* clone = fPicture->clone();
8175a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com            SkSafeUnref(clone);
8185a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        }
819c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
8205a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        return NULL == path;    // we don't have anything to write
8215a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    }
822c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
8235a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comprivate:
8245a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    virtual SkString getConfigNameInternal() SK_OVERRIDE {
8255a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        return SkString("picture_clone");
8265a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    }
8275a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com};
8285a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com
8295a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comPictureRenderer* CreatePictureCloneRenderer() {
8305a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    return SkNEW(PictureCloneRenderer);
8315a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com}
8325a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com
8339313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} // namespace sk_tools
834