/*
 * 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(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(&copy, &subset);
                            } else {
#endif
                                dst.copyTo(&copy);
#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");
    }
}
