SkMallocPixelRef.cpp revision 57212f9469c8056bab3c85243dbb904e386eab95
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkMallocPixelRef.h"
9#include "SkBitmap.h"
10#include "SkFlattenableBuffers.h"
11
12static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
13    if (info.fWidth < 0 ||
14        info.fHeight < 0 ||
15        (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
16        (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
17    {
18        return false;
19    }
20
21    // these seem like good checks, but currently we have (at least) tests
22    // that expect the pixelref to succeed even when there is a mismatch
23    // with colortables. fix?
24#if 0
25    if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
26        return false;
27    }
28    if (kIndex8_SkColorType != info.fColorType && NULL != ctable) {
29        return false;
30    }
31#endif
32    return true;
33}
34
35SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
36                                              void* addr,
37                                              size_t rowBytes,
38                                              SkColorTable* ctable) {
39    if (!is_valid(info, ctable)) {
40        return NULL;
41    }
42    return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
43}
44
45SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
46                                                size_t requestedRowBytes,
47                                                SkColorTable* ctable) {
48    if (!is_valid(info, ctable)) {
49        return NULL;
50    }
51
52    int32_t minRB = info.minRowBytes();
53    if (minRB < 0) {
54        return NULL;    // allocation will be too large
55    }
56    if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
57        return NULL;    // cannot meet requested rowbytes
58    }
59
60    int32_t rowBytes;
61    if (requestedRowBytes) {
62        rowBytes = requestedRowBytes;
63    } else {
64        rowBytes = minRB;
65    }
66
67    int64_t bigSize = (int64_t)info.fHeight * rowBytes;
68    if (!sk_64_isS32(bigSize)) {
69        return NULL;
70    }
71
72    size_t size = sk_64_asS32(bigSize);
73    void* addr = sk_malloc_flags(size, 0);
74    if (NULL == addr) {
75        return NULL;
76    }
77
78    return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
79}
80
81///////////////////////////////////////////////////////////////////////////////
82
83SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
84                                   size_t rowBytes, SkColorTable* ctable,
85                                   bool ownsPixels)
86    : INHERITED(info)
87    , fOwnPixels(ownsPixels)
88{
89    SkASSERT(is_valid(info, ctable));
90    SkASSERT(rowBytes >= info.minRowBytes());
91
92    if (kIndex_8_SkColorType != info.fColorType) {
93        ctable = NULL;
94    }
95
96    fStorage = storage;
97    fCTable = ctable;
98    fRB = rowBytes;
99    SkSafeRef(ctable);
100
101    this->setPreLocked(fStorage, fCTable);
102}
103
104SkMallocPixelRef::~SkMallocPixelRef() {
105    SkSafeUnref(fCTable);
106    if (fOwnPixels) {
107        sk_free(fStorage);
108    }
109}
110
111void* SkMallocPixelRef::onLockPixels(SkColorTable** ctable) {
112    *ctable = fCTable;
113    return fStorage;
114}
115
116void SkMallocPixelRef::onUnlockPixels() {
117    // nothing to do
118}
119
120size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
121    return this->info().getSafeSize(fRB);
122}
123
124void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
125    this->INHERITED::flatten(buffer);
126
127    buffer.write32(fRB);
128
129    // TODO: replace this bulk write with a chunky one that can trim off any
130    // trailing bytes on each scanline (in case rowbytes > width*size)
131    size_t size = this->info().getSafeSize(fRB);
132    buffer.writeByteArray(fStorage, size);
133    buffer.writeBool(fCTable != NULL);
134    if (fCTable) {
135        fCTable->writeToBuffer(buffer);
136    }
137}
138
139SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
140    : INHERITED(buffer, NULL)
141    , fOwnPixels(true)
142{
143    fRB = buffer.read32();
144    size_t size = this->info().getSafeSize(fRB);
145    if (buffer.validateAvailable(size)) {
146        fStorage = sk_malloc_throw(size);
147        buffer.readByteArray(fStorage, size);
148    } else {
149        fStorage = NULL;
150    }
151
152    if (buffer.readBool()) {
153        fCTable = SkNEW_ARGS(SkColorTable, (buffer));
154    } else {
155        fCTable = NULL;
156    }
157
158    this->setPreLocked(fStorage, fCTable);
159}
160