|  | /* | 
|  | * 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 { | 
|  | #if SK_SUPPORT_GPU | 
|  | CopyTilesRenderer::CopyTilesRenderer(const GrContext::Options& opts, int x, int y) | 
|  | : INHERITED(opts) | 
|  | , fXTilesPerLargeTile(x) | 
|  | , fYTilesPerLargeTile(y) { } | 
|  | #else | 
|  | CopyTilesRenderer::CopyTilesRenderer(int x, int y) | 
|  | : fXTilesPerLargeTile(x) | 
|  | , fYTilesPerLargeTile(y) { } | 
|  | #endif | 
|  | void CopyTilesRenderer::init(const SkPicture* pict, const SkString* writePath, | 
|  | const SkString* mismatchPath, const SkString* inputFilename, | 
|  | bool useChecksumBasedFilenames) { | 
|  | // Do not call INHERITED::init(), which would create a (potentially large) canvas which is | 
|  | // not used by bench_pictures. | 
|  | SkASSERT(pict != NULL); | 
|  | // Only work with absolute widths (as opposed to percentages). | 
|  | SkASSERT(this->getTileWidth() != 0 && this->getTileHeight() != 0); | 
|  | fPicture.reset(pict)->ref(); | 
|  | this->CopyString(&fWritePath, writePath); | 
|  | this->CopyString(&fMismatchPath, mismatchPath); | 
|  | this->CopyString(&fInputFilename, inputFilename); | 
|  | fUseChecksumBasedFilenames = useChecksumBasedFilenames; | 
|  | 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(SkBitmap** out) { | 
|  | int i = 0; | 
|  | bool success = true; | 
|  | SkBitmap dst; | 
|  | for (int x = 0; x < this->getViewWidth(); x += fLargeTileWidth) { | 
|  | for (int y = 0; y < this->getViewHeight(); y += fLargeTileHeight) { | 
|  | SkAutoCanvasRestore autoRestore(fCanvas, true); | 
|  | // Translate so that we draw the correct portion of the picture. | 
|  | // Perform a postTranslate so that the scaleFactor does not interfere with the | 
|  | // positioning. | 
|  | SkMatrix mat(fCanvas->getTotalMatrix()); | 
|  | mat.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); | 
|  | fCanvas->setMatrix(mat); | 
|  | // Draw the picture | 
|  | fCanvas->drawPicture(fPicture); | 
|  | // Now extract the picture into tiles | 
|  | SkBitmap baseBitmap; | 
|  | fCanvas->readPixels(SkIRect::MakeSize(fCanvas->getBaseLayerSize()), &baseBitmap); | 
|  | 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 (!fWritePath.isEmpty()) { | 
|  | // Similar to write() in PictureRenderer.cpp, but just encodes | 
|  | // a bitmap directly. | 
|  | // TODO: Share more common code with write() to do this, to properly | 
|  | // write out the JSON summary, etc. | 
|  | SkString pathWithNumber = SkOSPath::Join(fWritePath.c_str(), | 
|  | fInputFilename.c_str()); | 
|  | pathWithNumber.remove(pathWithNumber.size() - 4, 4); | 
|  | pathWithNumber.appendf("%i.png", i++); | 
|  | SkBitmap copy; | 
|  | #if SK_SUPPORT_GPU | 
|  | if (isUsingGpuDevice()) { | 
|  | dst.pixelRef()->readPixels(©, &subset); | 
|  | } else { | 
|  | #endif | 
|  | dst.copyTo(©); | 
|  | #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"); | 
|  | } | 
|  | } |