/*
* 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 "SamplePipeControllers.h"
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkGPipe.h"
#include "SkMatrix.h"
PipeController::PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc)
:fReader(target) {
fBlock = NULL;
fBlockSize = fBytesWritten = 0;
fReader.setBitmapDecoder(proc);
}
PipeController::~PipeController() {
sk_free(fBlock);
}
void* PipeController::requestBlock(size_t minRequest, size_t *actual) {
sk_free(fBlock);
fBlockSize = minRequest;
fBlock = sk_malloc_throw(fBlockSize);
fBytesWritten = 0;
*actual = fBlockSize;
return fBlock;
}
void PipeController::notifyWritten(size_t bytes) {
fStatus = fReader.playback(this->getData(), bytes);
SkASSERT(SkGPipeReader::kError_Status != fStatus);
fBytesWritten += bytes;
}
////////////////////////////////////////////////////////////////////////////////
TiledPipeController::TiledPipeController(const SkBitmap& bitmap,
SkPicture::InstallPixelRefProc proc,
const SkMatrix* initial)
: INHERITED(NULL, proc) {
int32_t top = 0;
int32_t bottom;
int32_t height = bitmap.height() / NumberOfTiles;
SkIRect rect;
for (int i = 0; i < NumberOfTiles; i++) {
bottom = i + 1 == NumberOfTiles ? bitmap.height() : top + height;
rect.setLTRB(0, top, bitmap.width(), bottom);
top = bottom;
SkDEBUGCODE(bool extracted = )bitmap.extractSubset(&fBitmaps[i], rect);
SkASSERT(extracted);
SkBaseDevice* device = new SkBitmapDevice(fBitmaps[i]);
SkCanvas* canvas = new SkCanvas(device);
device->unref();
if (initial != NULL) {
canvas->setMatrix(*initial);
}
canvas->translate(SkIntToScalar(-rect.left()),
SkIntToScalar(-rect.top()));
if (0 == i) {
fReader.setCanvas(canvas);
} else {
fReaders[i - 1].setCanvas(canvas);
fReaders[i - 1].setBitmapDecoder(proc);
}
canvas->unref();
}
}
void TiledPipeController::notifyWritten(size_t bytes) {
for (int i = 0; i < NumberOfTiles - 1; i++) {
fReaders[i].playback(this->getData(), bytes);
}
this->INHERITED::notifyWritten(bytes);
}
////////////////////////////////////////////////////////////////////////////////
ThreadSafePipeController::ThreadSafePipeController(int numberOfReaders)
: fAllocator(kMinBlockSize)
, fNumberOfReaders(numberOfReaders) {
fBlock = NULL;
fBytesWritten = 0;
}
void* ThreadSafePipeController::requestBlock(size_t minRequest, size_t *actual) {
if (fBlock) {
// Save the previous block for later
PipeBlock previousBloc(fBlock, fBytesWritten);
fBlockList.push(previousBloc);
}
int32_t blockSize = SkMax32(SkToS32(minRequest), kMinBlockSize);
fBlock = fAllocator.allocThrow(blockSize);
fBytesWritten = 0;
*actual = blockSize;
return fBlock;
}
void ThreadSafePipeController::notifyWritten(size_t bytes) {
fBytesWritten += bytes;
}
void ThreadSafePipeController::draw(SkCanvas* target) {
SkGPipeReader reader(target);
for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) {
reader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fBytes);
}
if (fBlock) {
reader.playback(fBlock, fBytesWritten);
}
}