Add a new PictureRenderer that draws the picture then breaks up into tiles.
Review URL: https://codereview.appspot.com/6820103
git-svn-id: http://skia.googlecode.com/svn/trunk@6333 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/CopyTilesRenderer.cpp b/tools/CopyTilesRenderer.cpp
new file mode 100644
index 0000000..553209c
--- /dev/null
+++ b/tools/CopyTilesRenderer.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "picture_utils.h"
+#include "CopyTilesRenderer.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkImageEncoder.h"
+#include "SkPicture.h"
+#include "SkPixelRef.h"
+#include "SkRect.h"
+#include "SkString.h"
+
+namespace sk_tools {
+ CopyTilesRenderer::CopyTilesRenderer(int x, int y)
+ : fXTilesPerLargeTile(x)
+ , fYTilesPerLargeTile(y) {
+ }
+ void CopyTilesRenderer::init(SkPicture* pict) {
+ SkASSERT(pict != NULL);
+ // Only work with absolute widths (as opposed to percentages).
+ SkASSERT(this->getTileWidth() != 0 && this->getTileHeight() != 0);
+ fPicture = pict;
+ fPicture->ref();
+ this->buildBBoxHierarchy();
+ // In order to avoid allocating a large canvas (particularly important for GPU), create one
+ // canvas that is a multiple of the tile size, and draw portions of the picture.
+ fLargeTileWidth = fXTilesPerLargeTile * this->getTileWidth();
+ fLargeTileHeight = fYTilesPerLargeTile * this->getTileHeight();
+ fCanvas.reset(this->INHERITED::setupCanvas(fLargeTileWidth, fLargeTileHeight));
+ }
+
+ bool CopyTilesRenderer::render(const SkString* path) {
+ int i = 0;
+ bool success = true;
+ SkBitmap dst;
+ for (int x = 0; x < fPicture->width(); x += fLargeTileWidth) {
+ for (int y = 0; y < fPicture->height(); y += fLargeTileHeight) {
+ SkAutoCanvasRestore autoRestore(fCanvas, true);
+ fCanvas->translate(SkIntToScalar(-x), SkIntToScalar(-y));
+ // Draw the picture
+ fCanvas->drawPicture(*fPicture);
+ // Now extract the picture into tiles
+ const SkBitmap& baseBitmap = fCanvas->getDevice()->accessBitmap(false);
+ SkIRect subset;
+ for (int tileY = 0; tileY < fLargeTileHeight; tileY += this->getTileHeight()) {
+ for (int tileX = 0; tileX < fLargeTileWidth; tileX += this->getTileWidth()) {
+ subset.set(tileX, tileY, tileX + this->getTileWidth(),
+ tileY + this->getTileHeight());
+ SkDEBUGCODE(bool extracted =)
+ baseBitmap.extractSubset(&dst, subset);
+ SkASSERT(extracted);
+ if (path != NULL) {
+ // Similar to writeAppendNumber in PictureRenderer.cpp, but just encodes
+ // a bitmap directly.
+ SkString pathWithNumber(*path);
+ pathWithNumber.appendf("%i.png", i++);
+ SkBitmap copy;
+#if SK_SUPPORT_GPU
+ if (isUsingGpuDevice()) {
+ dst.pixelRef()->readPixels(©, &subset);
+ } else {
+#endif
+ dst.copyTo(©, dst.config());
+#if SK_SUPPORT_GPU
+ }
+#endif
+ success &= SkImageEncoder::EncodeFile(pathWithNumber.c_str(), copy,
+ SkImageEncoder::kPNG_Type, 100);
+ }
+ }
+ }
+ }
+ }
+ return success;
+ }
+
+ SkString CopyTilesRenderer::getConfigNameInternal() {
+ return SkString("copy_tiles");
+ }
+}