blob: 96ea101f9f0d0e3367fa470ca114c6e2c8d3e058 [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
11#include "SkImageInfo.h"
12
13class SkColorTable;
14
15/**
16 * Pairs SkImageInfo with actual pixels and rowbytes. This class does not try to manage the
17 * lifetime of the pixel memory (nor the colortable if provided).
18 */
19class SkPixmap {
20public:
21 SkPixmap()
22 : fPixels(NULL), fCTable(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
23 {}
24
25 SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes,
26 SkColorTable* ctable = NULL)
27 : fPixels(addr), fCTable(ctable), fRowBytes(rowBytes), fInfo(info)
28 {
29 if (kIndex_8_SkColorType == info.colorType()) {
30 SkASSERT(ctable);
31 } else {
32 SkASSERT(NULL == ctable);
33 }
34 }
35
reed884e97c2015-05-26 11:31:54 -070036 void reset();
37 void reset(const SkImageInfo& info, const void* addr, size_t rowBytes,
38 SkColorTable* ctable = NULL);
39
reed92fc2ae2015-05-22 08:06:21 -070040 const SkImageInfo& info() const { return fInfo; }
41 size_t rowBytes() const { return fRowBytes; }
42 const void* addr() const { return fPixels; }
43 SkColorTable* ctable() const { return fCTable; }
44
45 int width() const { return fInfo.width(); }
46 int height() const { return fInfo.height(); }
47 SkColorType colorType() const { return fInfo.colorType(); }
48 SkAlphaType alphaType() const { return fInfo.alphaType(); }
49 bool isOpaque() const { return fInfo.isOpaque(); }
50
reed95d343f2015-05-23 13:21:06 -070051 uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); }
52 uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); }
reed92fc2ae2015-05-22 08:06:21 -070053 size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
54
55 const uint32_t* addr32() const {
56 SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType()));
57 return reinterpret_cast<const uint32_t*>(fPixels);
58 }
59
60 const uint16_t* addr16() const {
61 SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType()));
62 return reinterpret_cast<const uint16_t*>(fPixels);
63 }
64
65 const uint8_t* addr8() const {
66 SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType()));
67 return reinterpret_cast<const uint8_t*>(fPixels);
68 }
69
70 const uint32_t* addr32(int x, int y) const {
71 SkASSERT((unsigned)x < (unsigned)fInfo.width());
72 SkASSERT((unsigned)y < (unsigned)fInfo.height());
73 return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));
74 }
75 const uint16_t* addr16(int x, int y) const {
76 SkASSERT((unsigned)x < (unsigned)fInfo.width());
77 SkASSERT((unsigned)y < (unsigned)fInfo.height());
78 return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));
79 }
80 const uint8_t* addr8(int x, int y) const {
81 SkASSERT((unsigned)x < (unsigned)fInfo.width());
82 SkASSERT((unsigned)y < (unsigned)fInfo.height());
83 return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));
84 }
85 const void* addr(int x, int y) const {
86 return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
87 }
88
89 // Writable versions
90
91 void* writable_addr() const { return const_cast<void*>(fPixels); }
92 uint32_t* writable_addr32(int x, int y) const {
93 return const_cast<uint32_t*>(this->addr32(x, y));
94 }
95 uint16_t* writable_addr16(int x, int y) const {
96 return const_cast<uint16_t*>(this->addr16(x, y));
97 }
98 uint8_t* writable_addr8(int x, int y) const {
99 return const_cast<uint8_t*>(this->addr8(x, y));
100 }
101
reed95d343f2015-05-23 13:21:06 -0700102 // copy methods
103
104 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
105 int srcX, int srcY) const;
106 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
107 return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
108 }
109 bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
110 return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
111 }
112 bool readPixels(const SkPixmap& dst) const {
113 return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
114 }
115
reed92fc2ae2015-05-22 08:06:21 -0700116private:
117 const void* fPixels;
118 SkColorTable* fCTable;
119 size_t fRowBytes;
120 SkImageInfo fInfo;
121};
122
123/////////////////////////////////////////////////////////////////////////////////////////////
124
125class SkAutoPixmapUnlock : ::SkNoncopyable {
126public:
127 SkAutoPixmapUnlock() : fUnlockProc(NULL), fIsLocked(false) {}
128 SkAutoPixmapUnlock(const SkPixmap& pm, void (*unlock)(void*), void* ctx)
129 : fUnlockProc(unlock), fUnlockContext(ctx), fPixmap(pm), fIsLocked(true)
130 {}
131 ~SkAutoPixmapUnlock() { this->unlock(); }
132
133 /**
134 * Return the currently locked pixmap. Undefined if it has been unlocked.
135 */
136 const SkPixmap& pixmap() const {
137 SkASSERT(this->isLocked());
138 return fPixmap;
139 }
140
141 bool isLocked() const { return fIsLocked; }
142
143 /**
144 * Unlocks the pixmap. Can safely be called more than once as it will only call the underlying
145 * unlock-proc once.
146 */
147 void unlock() {
148 if (fUnlockProc) {
149 SkASSERT(fIsLocked);
150 fUnlockProc(fUnlockContext);
151 fUnlockProc = NULL;
152 fIsLocked = false;
153 }
154 }
155
156 /**
157 * If there is a currently locked pixmap, unlock it, then copy the specified pixmap
158 * and (optional) unlock proc/context.
159 */
160 void reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx);
161
162private:
163 void (*fUnlockProc)(void*);
164 void* fUnlockContext;
165 SkPixmap fPixmap;
166 bool fIsLocked;
167
168 friend class SkBitmap;
169};
170
171#endif