16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Copyright 2012 Google Inc. 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Use of this source code is governed by a BSD-style license that can be 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * found in the LICENSE file. 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "picture_utils.h" 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "CopyTilesRenderer.h" 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkCanvas.h" 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkDevice.h" 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkImageEncoder.h" 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkPicture.h" 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkPixelRef.h" 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkRect.h" 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "SkString.h" 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennnamespace sk_tools { 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CopyTilesRenderer::CopyTilesRenderer(int x, int y) 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn : fXTilesPerLargeTile(x) 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn , fYTilesPerLargeTile(y) { 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void CopyTilesRenderer::init(SkPicture* pict, const SkString* writePath, 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const SkString* mismatchPath, const SkString* inputFilename, 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool useChecksumBasedFilenames) { 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Do not call INHERITED::init(), which would create a (potentially large) canvas which is 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // not used by bench_pictures. 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn SkASSERT(pict != NULL); 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Only work with absolute widths (as opposed to percentages). 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn SkASSERT(this->getTileWidth() != 0 && this->getTileHeight() != 0); 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fPicture.reset(pict)->ref(); 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn this->CopyString(&fWritePath, writePath); 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn this->CopyString(&fMismatchPath, mismatchPath); 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn this->CopyString(&fInputFilename, inputFilename); 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fUseChecksumBasedFilenames = useChecksumBasedFilenames; 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn this->buildBBoxHierarchy(); 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // In order to avoid allocating a large canvas (particularly important for GPU), create one 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // canvas that is a multiple of the tile size, and draw portions of the picture. 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fLargeTileWidth = fXTilesPerLargeTile * this->getTileWidth(); 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fLargeTileHeight = fYTilesPerLargeTile * this->getTileHeight(); 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fCanvas.reset(this->INHERITED::setupCanvas(fLargeTileWidth, fLargeTileHeight)); 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool CopyTilesRenderer::render(SkBitmap** out) { 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i = 0; 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool success = true; 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn SkBitmap dst; 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int x = 0; x < this->getViewWidth(); x += fLargeTileWidth) { 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int y = 0; y < this->getViewHeight(); y += fLargeTileHeight) { 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn SkAutoCanvasRestore autoRestore(fCanvas, true); 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Translate so that we draw the correct portion of the picture. 52 // Perform a postTranslate so that the scaleFactor does not interfere with the 53 // positioning. 54 SkMatrix mat(fCanvas->getTotalMatrix()); 55 mat.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 56 fCanvas->setMatrix(mat); 57 // Draw the picture 58 fCanvas->drawPicture(fPicture); 59 // Now extract the picture into tiles 60 const SkBitmap& baseBitmap = fCanvas->getDevice()->accessBitmap(false); 61 SkIRect subset; 62 for (int tileY = 0; tileY < fLargeTileHeight; tileY += this->getTileHeight()) { 63 for (int tileX = 0; tileX < fLargeTileWidth; tileX += this->getTileWidth()) { 64 subset.set(tileX, tileY, tileX + this->getTileWidth(), 65 tileY + this->getTileHeight()); 66 SkDEBUGCODE(bool extracted =) 67 baseBitmap.extractSubset(&dst, subset); 68 SkASSERT(extracted); 69 if (!fWritePath.isEmpty()) { 70 // Similar to write() in PictureRenderer.cpp, but just encodes 71 // a bitmap directly. 72 // TODO: Share more common code with write() to do this, to properly 73 // write out the JSON summary, etc. 74 SkString pathWithNumber = SkOSPath::SkPathJoin(fWritePath.c_str(), 75 fInputFilename.c_str()); 76 pathWithNumber.remove(pathWithNumber.size() - 4, 4); 77 pathWithNumber.appendf("%i.png", i++); 78 SkBitmap copy; 79#if SK_SUPPORT_GPU 80 if (isUsingGpuDevice()) { 81 dst.pixelRef()->readPixels(©, &subset); 82 } else { 83#endif 84 dst.copyTo(©); 85#if SK_SUPPORT_GPU 86 } 87#endif 88 success &= SkImageEncoder::EncodeFile(pathWithNumber.c_str(), copy, 89 SkImageEncoder::kPNG_Type, 100); 90 } 91 } 92 } 93 } 94 } 95 return success; 96 } 97 98 SkString CopyTilesRenderer::getConfigNameInternal() { 99 return SkString("copy_tiles"); 100 } 101} 102