blob: faae85e797e7f262f63a165f2fa9e690779236c2 [file] [log] [blame]
reed92fc2ae2015-05-22 08:06:21 -07001/*
2 * Copyright 2015 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#ifndef SkPixmap_DEFINED
9#define SkPixmap_DEFINED
10
reed7aefe032015-06-08 10:22:22 -070011#include "SkColor.h"
reed92fc2ae2015-05-22 08:06:21 -070012#include "SkImageInfo.h"
13
14class SkColorTable;
reed183b57f2015-06-05 14:33:17 -070015struct SkMask;
reed92fc2ae2015-05-22 08:06:21 -070016
17/**
18 * Pairs SkImageInfo with actual pixels and rowbytes. This class does not try to manage the
19 * lifetime of the pixel memory (nor the colortable if provided).
20 */
fmalita9a5d1ab2015-07-27 10:27:28 -070021class SK_API SkPixmap {
reed92fc2ae2015-05-22 08:06:21 -070022public:
23 SkPixmap()
24 : fPixels(NULL), fCTable(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
25 {}
26
27 SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes,
28 SkColorTable* ctable = NULL)
29 : fPixels(addr), fCTable(ctable), fRowBytes(rowBytes), fInfo(info)
30 {
31 if (kIndex_8_SkColorType == info.colorType()) {
32 SkASSERT(ctable);
33 } else {
34 SkASSERT(NULL == ctable);
35 }
36 }
37
reed884e97c2015-05-26 11:31:54 -070038 void reset();
39 void reset(const SkImageInfo& info, const void* addr, size_t rowBytes,
40 SkColorTable* ctable = NULL);
reed183b57f2015-06-05 14:33:17 -070041 void reset(const SkImageInfo& info) {
42 this->reset(info, NULL, 0, NULL);
43 }
44
45 /**
46 * If supported, set this pixmap to point to the pixels in the specified mask and return true.
47 * On failure, return false and set this pixmap to empty.
48 */
49 bool SK_WARN_UNUSED_RESULT reset(const SkMask&);
50
51 /**
52 * Computes the intersection of area and this pixmap. If that intersection is non-empty,
53 * set subset to that intersection and return true.
54 *
55 * On failure, return false and ignore the subset parameter.
56 */
57 bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const;
reed884e97c2015-05-26 11:31:54 -070058
reed92fc2ae2015-05-22 08:06:21 -070059 const SkImageInfo& info() const { return fInfo; }
60 size_t rowBytes() const { return fRowBytes; }
61 const void* addr() const { return fPixels; }
62 SkColorTable* ctable() const { return fCTable; }
63
64 int width() const { return fInfo.width(); }
65 int height() const { return fInfo.height(); }
66 SkColorType colorType() const { return fInfo.colorType(); }
67 SkAlphaType alphaType() const { return fInfo.alphaType(); }
68 bool isOpaque() const { return fInfo.isOpaque(); }
69
reedad7ae6c2015-06-04 14:12:25 -070070 SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }
71
reed95d343f2015-05-23 13:21:06 -070072 uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); }
73 uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); }
reed92fc2ae2015-05-22 08:06:21 -070074 size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
75
76 const uint32_t* addr32() const {
77 SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType()));
78 return reinterpret_cast<const uint32_t*>(fPixels);
79 }
80
81 const uint16_t* addr16() const {
82 SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType()));
83 return reinterpret_cast<const uint16_t*>(fPixels);
84 }
85
86 const uint8_t* addr8() const {
87 SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType()));
88 return reinterpret_cast<const uint8_t*>(fPixels);
89 }
90
91 const uint32_t* addr32(int x, int y) const {
92 SkASSERT((unsigned)x < (unsigned)fInfo.width());
93 SkASSERT((unsigned)y < (unsigned)fInfo.height());
94 return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));
95 }
96 const uint16_t* addr16(int x, int y) const {
97 SkASSERT((unsigned)x < (unsigned)fInfo.width());
98 SkASSERT((unsigned)y < (unsigned)fInfo.height());
99 return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));
100 }
101 const uint8_t* addr8(int x, int y) const {
102 SkASSERT((unsigned)x < (unsigned)fInfo.width());
103 SkASSERT((unsigned)y < (unsigned)fInfo.height());
104 return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));
105 }
106 const void* addr(int x, int y) const {
107 return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
108 }
109
110 // Writable versions
111
112 void* writable_addr() const { return const_cast<void*>(fPixels); }
113 uint32_t* writable_addr32(int x, int y) const {
114 return const_cast<uint32_t*>(this->addr32(x, y));
115 }
116 uint16_t* writable_addr16(int x, int y) const {
117 return const_cast<uint16_t*>(this->addr16(x, y));
118 }
119 uint8_t* writable_addr8(int x, int y) const {
120 return const_cast<uint8_t*>(this->addr8(x, y));
121 }
122
reed95d343f2015-05-23 13:21:06 -0700123 // copy methods
124
125 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
126 int srcX, int srcY) const;
127 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
128 return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
129 }
130 bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
131 return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
132 }
133 bool readPixels(const SkPixmap& dst) const {
134 return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
135 }
136
reed7aefe032015-06-08 10:22:22 -0700137 /**
138 * Returns true if pixels were written to (e.g. if colorType is kUnknown_SkColorType, this
139 * will return false). If subset does not intersect the bounds of this pixmap, returns false.
140 */
141 bool erase(SkColor, const SkIRect& subset) const;
142
143 bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
144
reed92fc2ae2015-05-22 08:06:21 -0700145private:
146 const void* fPixels;
147 SkColorTable* fCTable;
148 size_t fRowBytes;
149 SkImageInfo fInfo;
150};
151
152/////////////////////////////////////////////////////////////////////////////////////////////
153
fmalita9a5d1ab2015-07-27 10:27:28 -0700154class SK_API SkAutoPixmapStorage : public SkPixmap {
reed183b57f2015-06-05 14:33:17 -0700155public:
156 SkAutoPixmapStorage();
157 ~SkAutoPixmapStorage();
158
159 /**
160 * Try to allocate memory for the pixels needed to match the specified Info. On success
161 * return true and fill out the pixmap to point to that memory. The storage will be freed
162 * when this object is destroyed, or if another call to tryAlloc() or alloc() is made.
163 *
164 * On failure, return false and reset() the pixmap to empty.
165 */
166 bool tryAlloc(const SkImageInfo&);
167
168 /**
169 * Allocate memory for the pixels needed to match the specified Info and fill out the pixmap
170 * to point to that memory. The storage will be freed when this object is destroyed,
171 * or if another call to tryAlloc() or alloc() is made.
172 *
173 * If the memory cannot be allocated, calls sk_throw().
174 */
175 void alloc(const SkImageInfo&);
176
reed7aefe032015-06-08 10:22:22 -0700177 // We wrap these so we can clear our internal storage
178
179 void reset() {
180 this->freeStorage();
181 this->INHERITED::reset();
182 }
183 void reset(const SkImageInfo& info, const void* addr, size_t rb, SkColorTable* ctable = NULL) {
184 this->freeStorage();
185 this->INHERITED::reset(info, addr, rb, ctable);
186 }
187 void reset(const SkImageInfo& info) {
188 this->freeStorage();
189 this->INHERITED::reset(info);
190 }
191 bool SK_WARN_UNUSED_RESULT reset(const SkMask& mask) {
192 this->freeStorage();
193 return this->INHERITED::reset(mask);
194 }
195
reed183b57f2015-06-05 14:33:17 -0700196private:
197 void* fStorage;
reed7aefe032015-06-08 10:22:22 -0700198
199 void freeStorage() {
200 sk_free(fStorage);
201 fStorage = NULL;
202 }
203
204 typedef SkPixmap INHERITED;
reed183b57f2015-06-05 14:33:17 -0700205};
206
207/////////////////////////////////////////////////////////////////////////////////////////////
208
fmalita9a5d1ab2015-07-27 10:27:28 -0700209class SK_API SkAutoPixmapUnlock : ::SkNoncopyable {
reed92fc2ae2015-05-22 08:06:21 -0700210public:
211 SkAutoPixmapUnlock() : fUnlockProc(NULL), fIsLocked(false) {}
212 SkAutoPixmapUnlock(const SkPixmap& pm, void (*unlock)(void*), void* ctx)
213 : fUnlockProc(unlock), fUnlockContext(ctx), fPixmap(pm), fIsLocked(true)
214 {}
215 ~SkAutoPixmapUnlock() { this->unlock(); }
216
217 /**
218 * Return the currently locked pixmap. Undefined if it has been unlocked.
219 */
220 const SkPixmap& pixmap() const {
221 SkASSERT(this->isLocked());
222 return fPixmap;
223 }
224
225 bool isLocked() const { return fIsLocked; }
226
227 /**
228 * Unlocks the pixmap. Can safely be called more than once as it will only call the underlying
229 * unlock-proc once.
230 */
231 void unlock() {
232 if (fUnlockProc) {
233 SkASSERT(fIsLocked);
234 fUnlockProc(fUnlockContext);
235 fUnlockProc = NULL;
236 fIsLocked = false;
237 }
238 }
239
240 /**
241 * If there is a currently locked pixmap, unlock it, then copy the specified pixmap
242 * and (optional) unlock proc/context.
243 */
244 void reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx);
245
246private:
247 void (*fUnlockProc)(void*);
248 void* fUnlockContext;
249 SkPixmap fPixmap;
250 bool fIsLocked;
251
252 friend class SkBitmap;
253};
254
255#endif