/* * 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); } }