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