'<(skia_src_path)/doc/SkDocument.cpp',
- '<(skia_src_path)/image/SkDataPixelRef.cpp',
'<(skia_src_path)/image/SkImage.cpp',
'<(skia_src_path)/image/SkImagePriv.cpp',
'<(skia_src_path)/image/SkImage_Codec.cpp',
'../tests/LListTest.cpp',
'../tests/LayerDrawLooperTest.cpp',
'../tests/MD5Test.cpp',
+ '../tests/MallocPixelRefTest.cpp',
'../tests/MathTest.cpp',
'../tests/MatrixTest.cpp',
'../tests/Matrix44Test.cpp',
static SkMallocPixelRef* NewAllocate(const SkImageInfo& info,
size_t rowBytes, SkColorTable*);
+ /**
+ * Return a new SkMallocPixelRef with the provided pixel storage,
+ * rowBytes, and optional colortable. On destruction, ReleaseProc
+ * will be called.
+ *
+ * This pixelref will ref() the specified colortable (if not NULL).
+ *
+ * Returns NULL on failure.
+ */
+ typedef void (*ReleaseProc)(void* addr, void* context);
+ static SkMallocPixelRef* NewWithProc(const SkImageInfo& info,
+ size_t rowBytes, SkColorTable*,
+ void* addr, ReleaseProc proc,
+ void* context);
+
+ /**
+ * Return a new SkMallocPixelRef that will use the provided
+ * SkData, rowBytes, and optional colortable as pixel storage.
+ * The SkData will be ref()ed and on destruction of the PielRef,
+ * the SkData will be unref()ed.
+ *
+ * @param offset (in bytes) into the provided SkData that the
+ * first pixel is located at.
+ *
+ * This pixelref will ref() the specified colortable (if not NULL).
+ *
+ * Returns NULL on failure.
+ */
+ static SkMallocPixelRef* NewWithData(const SkImageInfo& info,
+ size_t rowBytes,
+ SkColorTable* ctable,
+ SkData* data,
+ size_t offset = 0);
+
void* getAddr() const { return fStorage; }
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
protected:
+ // The ownPixels version of this constructor is deprecated.
SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*,
bool ownPixels);
SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
void* fStorage;
SkColorTable* fCTable;
size_t fRB;
- const bool fOwnPixels;
+ ReleaseProc fReleaseProc;
+ void* fReleaseProcContext;
+
+ SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*,
+ ReleaseProc proc, void* context);
typedef SkPixelRef INHERITED;
};
#include "SkBitmap.h"
#include "SkFlattenableBuffers.h"
+// assumes ptr was allocated via sk_malloc
+static void sk_free_releaseproc(void* ptr, void*) {
+ sk_free(ptr);
+}
+
static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
if (info.fWidth < 0 ||
info.fHeight < 0 ||
if (!is_valid(info, ctable)) {
return NULL;
}
- return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
+ return SkNEW_ARGS(SkMallocPixelRef,
+ (info, addr, rowBytes, ctable, NULL, NULL));
}
SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
}
size_t size = sk_64_asS32(bigSize);
+ SkASSERT(size >= info.getSafeSize(rowBytes));
void* addr = sk_malloc_flags(size, 0);
if (NULL == addr) {
return NULL;
}
- return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
+ return SkNEW_ARGS(SkMallocPixelRef,
+ (info, addr, rowBytes, ctable,
+ sk_free_releaseproc, NULL));
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
+ size_t rowBytes,
+ SkColorTable* ctable,
+ void* addr,
+ SkMallocPixelRef::ReleaseProc proc,
+ void* context) {
+ if (!is_valid(info, ctable)) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkMallocPixelRef,
+ (info, addr, rowBytes, ctable, proc, context));
+}
+
+static void sk_data_releaseproc(void*, void* dataPtr) {
+ (static_cast<SkData*>(dataPtr))->unref();
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
+ size_t rowBytes,
+ SkColorTable* ctable,
+ SkData* data,
+ size_t offset) {
+ SkASSERT(data != NULL);
+ SkASSERT(offset <= data->size());
+ if (!is_valid(info, ctable)) {
+ return NULL;
+ }
+ if ((rowBytes < info.minRowBytes())
+ || ((data->size() - offset) < info.getSafeSize(rowBytes))) {
+ return NULL;
+ }
+ data->ref();
+ const void* ptr = static_cast<const void*>(data->bytes() + offset);
+ SkMallocPixelRef* pr
+ = SkNEW_ARGS(SkMallocPixelRef,
+ (info, const_cast<void*>(ptr), rowBytes, ctable,
+ sk_data_releaseproc, static_cast<void*>(data)));
+ SkASSERT(pr != NULL);
+ // We rely on the immutability of the pixels to make the
+ // const_cast okay.
+ pr->setImmutable();
+ return pr;
}
///////////////////////////////////////////////////////////////////////////////
size_t rowBytes, SkColorTable* ctable,
bool ownsPixels)
: INHERITED(info)
- , fOwnPixels(ownsPixels)
+ , fReleaseProc(ownsPixels ? sk_free_releaseproc : NULL)
+ , fReleaseProcContext(NULL) {
+ // This constructor is now DEPRICATED.
+ SkASSERT(is_valid(info, ctable));
+ SkASSERT(rowBytes >= info.minRowBytes());
+
+ if (kIndex_8_SkColorType != info.fColorType) {
+ ctable = NULL;
+ }
+
+ fStorage = storage;
+ fCTable = ctable;
+ fRB = rowBytes;
+ SkSafeRef(ctable);
+
+ this->setPreLocked(fStorage, fCTable);
+}
+
+SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
+ size_t rowBytes, SkColorTable* ctable,
+ SkMallocPixelRef::ReleaseProc proc,
+ void* context)
+ : INHERITED(info)
+ , fReleaseProc(proc)
+ , fReleaseProcContext(context)
{
SkASSERT(is_valid(info, ctable));
SkASSERT(rowBytes >= info.minRowBytes());
this->setPreLocked(fStorage, fCTable);
}
+
SkMallocPixelRef::~SkMallocPixelRef() {
SkSafeUnref(fCTable);
- if (fOwnPixels) {
- sk_free(fStorage);
+ if (fReleaseProc != NULL) {
+ fReleaseProc(fStorage, fReleaseProcContext);
}
}
SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer, NULL)
- , fOwnPixels(true)
+ , fReleaseProc(sk_free_releaseproc)
+ , fReleaseProcContext(NULL)
{
fRB = buffer.read32();
size_t size = buffer.isValid() ? this->info().getSafeSize(fRB) : 0;
+++ /dev/null
-/*
- * 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 "SkDataPixelRef.h"
-#include "SkData.h"
-#include "SkFlattenableBuffers.h"
-
-SkDataPixelRef::SkDataPixelRef(const SkImageInfo& info, SkData* data)
- : INHERITED(info)
- , fData(data)
-{
- fData->ref();
- this->setPreLocked(const_cast<void*>(fData->data()), NULL);
-}
-
-SkDataPixelRef::~SkDataPixelRef() {
- fData->unref();
-}
-
-void* SkDataPixelRef::onLockPixels(SkColorTable** ct) {
- *ct = NULL;
- return const_cast<void*>(fData->data());
-}
-
-void SkDataPixelRef::onUnlockPixels() {
- // nothing to do
-}
-
-size_t SkDataPixelRef::getAllocatedSizeInBytes() const {
- return fData ? fData->size() : 0;
-}
-
-void SkDataPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- buffer.writeDataAsByteArray(fData);
-}
-
-SkDataPixelRef::SkDataPixelRef(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer, NULL) {
- fData = buffer.readByteArrayAsData();
- this->setPreLocked(const_cast<void*>(fData->data()), NULL);
-}
+++ /dev/null
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkDataPixelRef_DEFINED
-#define SkDataPixelRef_DEFINED
-
-#include "SkPixelRef.h"
-
-class SkData;
-
-class SkDataPixelRef : public SkPixelRef {
-public:
- SkDataPixelRef(const SkImageInfo&, SkData* data);
- virtual ~SkDataPixelRef();
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataPixelRef)
-
-protected:
- virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
- virtual void onUnlockPixels() SK_OVERRIDE;
- virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
-
- SkDataPixelRef(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
-
-private:
- SkData* fData;
-
- typedef SkPixelRef INHERITED;
-};
-
-#endif
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkData.h"
-#include "SkDataPixelRef.h"
+#include "SkMallocPixelRef.h"
class SkImage_Raster : public SkImage_Base {
public:
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
: INHERITED(info.fWidth, info.fHeight) {
fBitmap.setConfig(info, rowBytes);
- fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (info, data)))->unref();
+ SkAutoTUnref<SkPixelRef> ref(
+ SkMallocPixelRef::NewWithData(info, rowBytes, NULL, data, 0));
+ fBitmap.setPixelRef(ref, 0);
fBitmap.setImmutable();
}
--- /dev/null
+/*
+ * 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 "SkData.h"
+#include "SkMallocPixelRef.h"
+#include "Test.h"
+#include "TestClassDef.h"
+
+static void delete_uint8_proc(void* ptr, void*) {
+ delete[] static_cast<uint8_t*>(ptr);
+}
+
+static void set_to_one_proc(void*, void* context) {
+ *(static_cast<int*>(context)) = 1;
+}
+
+/**
+ * This test contains basic sanity checks concerning SkMallocPixelRef.
+ */
+DEF_TEST(MallocPixelRef, reporter) {
+ REPORTER_ASSERT(reporter, true);
+ SkImageInfo info = {10, 13, kPMColor_SkColorType, kPremul_SkAlphaType};
+ {
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewAllocate(info, info.minRowBytes() - 1, NULL));
+ // rowbytes too small.
+ REPORTER_ASSERT(reporter, NULL == pr.get());
+ }
+ {
+ size_t rowBytes = info.minRowBytes() - 1;
+ size_t size = info.getSafeSize(rowBytes);
+ void* addr = sk_malloc_throw(size);
+ SkAutoDataUnref data(SkData::NewFromMalloc(addr, size));
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewWithData(info, rowBytes,
+ NULL, data.get()));
+ // rowbytes too small.
+ REPORTER_ASSERT(reporter, NULL == pr.get());
+ }
+ {
+ size_t rowBytes = info.minRowBytes() + 2;
+ size_t size = info.getSafeSize(rowBytes) - 1;
+ void* addr = sk_malloc_throw(size);
+ SkAutoDataUnref data(SkData::NewFromMalloc(addr, size));
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewWithData(info, rowBytes, NULL,
+ data.get()));
+ // data too small.
+ REPORTER_ASSERT(reporter, NULL == pr.get());
+ }
+ size_t rowBytes = info.minRowBytes() + 7;
+ size_t size = info.getSafeSize(rowBytes) + 9;
+ {
+ SkAutoMalloc memory(size);
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewDirect(info, memory.get(), rowBytes, NULL));
+ REPORTER_ASSERT(reporter, pr.get() != NULL);
+ REPORTER_ASSERT(reporter, memory.get() == pr->pixels());
+ }
+ {
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewAllocate(info, rowBytes, NULL));
+ REPORTER_ASSERT(reporter, pr.get() != NULL);
+ REPORTER_ASSERT(reporter, NULL != pr->pixels());
+ }
+ {
+ void* addr = static_cast<void*>(new uint8_t[size]);
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewWithProc(info, rowBytes, NULL, addr,
+ delete_uint8_proc, NULL));
+ REPORTER_ASSERT(reporter, pr.get() != NULL);
+ REPORTER_ASSERT(reporter, addr == pr->pixels());
+ }
+ {
+ int x = 0;
+ SkAutoMalloc memory(size);
+ REPORTER_ASSERT(reporter, memory.get() != NULL);
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewWithProc(info, rowBytes, NULL,
+ memory.get(), set_to_one_proc,
+ static_cast<void*>(&x)));
+ REPORTER_ASSERT(reporter, pr.get() != NULL);
+ REPORTER_ASSERT(reporter, memory.get() == pr->pixels());
+ REPORTER_ASSERT(reporter, 0 == x);
+ pr.reset(NULL);
+ // make sure that set_to_one_proc was called.
+ REPORTER_ASSERT(reporter, 1 == x);
+ }
+ {
+ void* addr = static_cast<void*>(new uint8_t[size]);
+ REPORTER_ASSERT(reporter, addr != NULL);
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewWithProc(info, rowBytes, NULL, addr,
+ delete_uint8_proc, NULL));
+ REPORTER_ASSERT(reporter, addr == pr->pixels());
+ }
+ {
+ void* addr = sk_malloc_throw(size);
+ SkAutoDataUnref data(SkData::NewFromMalloc(addr, size));
+ REPORTER_ASSERT(reporter, data.get() != NULL);
+ SkData* dataPtr = data.get();
+ REPORTER_ASSERT(reporter, dataPtr->unique());
+ SkAutoTUnref<SkMallocPixelRef> pr(
+ SkMallocPixelRef::NewWithData(info, rowBytes, NULL, data.get(), 4));
+ REPORTER_ASSERT(reporter, !(dataPtr->unique()));
+ data.reset(NULL);
+ REPORTER_ASSERT(reporter, dataPtr->unique());
+ REPORTER_ASSERT(reporter,
+ static_cast<const void*>(dataPtr->bytes() + 4) == pr->pixels());
+ }
+}
+