/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkCachingPixelRef.h" #include "SkBitmapCache.h" #include "SkRect.h" bool SkCachingPixelRef::Install(SkImageGenerator* generator, SkBitmap* dst) { SkASSERT(dst != NULL); if (NULL == generator) { return false; } const SkImageInfo info = generator->getInfo(); if (!dst->setInfo(info)) { SkDELETE(generator); return false; } SkAutoTUnref<SkCachingPixelRef> ref(SkNEW_ARGS(SkCachingPixelRef, (info, generator, dst->rowBytes()))); dst->setPixelRef(ref); return true; } SkCachingPixelRef::SkCachingPixelRef(const SkImageInfo& info, SkImageGenerator* generator, size_t rowBytes) : INHERITED(info) , fImageGenerator(generator) , fErrorInDecoding(false) , fRowBytes(rowBytes) { SkASSERT(fImageGenerator != NULL); } SkCachingPixelRef::~SkCachingPixelRef() { SkDELETE(fImageGenerator); // Assert always unlock before unref. } bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) { if (fErrorInDecoding) { return false; // don't try again. } const SkImageInfo& info = this->info(); if (!SkBitmapCache::Find( this->getGenerationID(), info.bounds(), &fLockedBitmap)) { // Cache has been purged, must re-decode. if (!fLockedBitmap.tryAllocPixels(info, fRowBytes)) { fErrorInDecoding = true; return false; } const SkImageGenerator::Result result = fImageGenerator->getPixels(info, fLockedBitmap.getPixels(), fRowBytes); switch (result) { case SkImageGenerator::kIncompleteInput: case SkImageGenerator::kSuccess: break; default: fErrorInDecoding = true; return false; } fLockedBitmap.setImmutable(); SkBitmapCache::Add(this, info.bounds(), fLockedBitmap); } // Now bitmap should contain a concrete PixelRef of the decoded image. void* pixels = fLockedBitmap.getPixels(); SkASSERT(pixels != NULL); rec->fPixels = pixels; rec->fColorTable = NULL; rec->fRowBytes = fLockedBitmap.rowBytes(); return true; } void SkCachingPixelRef::onUnlockPixels() { fLockedBitmap.reset(); }