1/*
2 * Copyright 2006 The Android Open Source Project
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 SkMask_DEFINED
9#define SkMask_DEFINED
10
11#include "include/core/SkRect.h"
12#include "include/private/SkColorData.h"
13#include "include/private/SkMacros.h"
14#include "include/private/SkTemplates.h"
15
16#include <memory>
17
18/** \class SkMask
19 SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
20 the 3-channel 3D format. These are passed to SkMaskFilter objects.
21*/
22struct SkMask {
23 SkMask() : fImage(nullptr) {}
24
25 enum Format {
26 kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
27 kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
28 k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
29 kARGB32_Format, //!< SkPMColor
30 kLCD16_Format, //!< 565 alpha for r/g/b
31 kSDF_Format, //!< 8bits representing signed distance field
32 };
33
34 enum {
35 kCountMaskFormats = kSDF_Format + 1
36 };
37
38 uint8_t* fImage;
39 SkIRect fBounds;
40 uint32_t fRowBytes;
41 Format fFormat;
42
43 static bool IsValidFormat(uint8_t format) { return format < kCountMaskFormats; }
44
45 /** Returns true if the mask is empty: i.e. it has an empty bounds.
46 */
47 bool isEmpty() const { return fBounds.isEmpty(); }
48
49 /** Return the byte size of the mask, assuming only 1 plane.
50 Does not account for k3D_Format. For that, use computeTotalImageSize().
51 If there is an overflow of 32bits, then returns 0.
52 */
53 size_t computeImageSize() const;
54
55 /** Return the byte size of the mask, taking into account
56 any extra planes (e.g. k3D_Format).
57 If there is an overflow of 32bits, then returns 0.
58 */
59 size_t computeTotalImageSize() const;
60
61 /** Returns the address of the byte that holds the specified bit.
62 Asserts that the mask is kBW_Format, and that x,y are in range.
63 x,y are in the same coordiate space as fBounds.
64 */
65 uint8_t* getAddr1(int x, int y) const {
66 SkASSERT(kBW_Format == fFormat);
67 SkASSERT(fBounds.contains(x, y));
68 SkASSERT(fImage != nullptr);
69 return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes;
70 }
71
72 /** Returns the address of the specified byte.
73 Asserts that the mask is kA8_Format, and that x,y are in range.
74 x,y are in the same coordiate space as fBounds.
75 */
76 uint8_t* getAddr8(int x, int y) const {
77 SkASSERT(kA8_Format == fFormat || kSDF_Format == fFormat);
78 SkASSERT(fBounds.contains(x, y));
79 SkASSERT(fImage != nullptr);
80 return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
81 }
82
83 /**
84 * Return the address of the specified 16bit mask. In the debug build,
85 * this asserts that the mask's format is kLCD16_Format, and that (x,y)
86 * are contained in the mask's fBounds.
87 */
88 uint16_t* getAddrLCD16(int x, int y) const {
89 SkASSERT(kLCD16_Format == fFormat);
90 SkASSERT(fBounds.contains(x, y));
91 SkASSERT(fImage != nullptr);
92 uint16_t* row = (uint16_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
93 return row + (x - fBounds.fLeft);
94 }
95
96 /**
97 * Return the address of the specified 32bit mask. In the debug build,
98 * this asserts that the mask's format is 32bits, and that (x,y)
99 * are contained in the mask's fBounds.
100 */
101 uint32_t* getAddr32(int x, int y) const {
102 SkASSERT(kARGB32_Format == fFormat);
103 SkASSERT(fBounds.contains(x, y));
104 SkASSERT(fImage != nullptr);
105 uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
106 return row + (x - fBounds.fLeft);
107 }
108
109 /**
110 * Returns the address of the specified pixel, computing the pixel-size
111 * at runtime based on the mask format. This will be slightly slower than
112 * using one of the routines where the format is implied by the name
113 * e.g. getAddr8 or getAddr32.
114 *
115 * x,y must be contained by the mask's bounds (this is asserted in the
116 * debug build, but not checked in the release build.)
117 *
118 * This should not be called with kBW_Format, as it will give unspecified
119 * results (and assert in the debug build).
120 */
121 void* getAddr(int x, int y) const;
122
123 enum AllocType {
124 kUninit_Alloc,
125 kZeroInit_Alloc,
126 };
127 static uint8_t* AllocImage(size_t bytes, AllocType = kUninit_Alloc);
128 static void FreeImage(void* image);
129
130 enum CreateMode {
131 kJustComputeBounds_CreateMode, //!< compute bounds and return
132 kJustRenderImage_CreateMode, //!< render into preallocate mask
133 kComputeBoundsAndRenderImage_CreateMode //!< compute bounds, alloc image and render into it
134 };
135
136 /** Iterates over the coverage values along a scanline in a given SkMask::Format. Provides
137 * constructor, copy constructor for creating
138 * operator++, operator-- for iterating over the coverage values on a scanline
139 * operator>>= to add row bytes
140 * operator* to get the coverage value at the current location
141 * operator< to compare two iterators
142 */
143 template <Format F> struct AlphaIter;
144
145 /**
146 * Returns initial destination mask data padded by radiusX and radiusY
147 */
148 static SkMask PrepareDestination(int radiusX, int radiusY, const SkMask& src);
149};
150
151template <> struct SkMask::AlphaIter<SkMask::kBW_Format> {
152 AlphaIter(const uint8_t* ptr, int offset) : fPtr(ptr), fOffset(7 - offset) {}
153 AlphaIter(const AlphaIter& that) : fPtr(that.fPtr), fOffset(that.fOffset) {}
154 AlphaIter& operator++() {
155 if (0 < fOffset ) {
156 --fOffset;
157 } else {
158 ++fPtr;
159 fOffset = 7;
160 }
161 return *this;
162 }
163 AlphaIter& operator--() {
164 if (fOffset < 7) {
165 ++fOffset;
166 } else {
167 --fPtr;
168 fOffset = 0;
169 }
170 return *this;
171 }
172 AlphaIter& operator>>=(uint32_t rb) {
173 fPtr = SkTAddOffset<const uint8_t>(fPtr, rb);
174 return *this;
175 }
176 uint8_t operator*() const { return ((*fPtr) >> fOffset) & 1 ? 0xFF : 0; }
177 bool operator<(const AlphaIter& that) const {
178 return fPtr < that.fPtr || (fPtr == that.fPtr && fOffset > that.fOffset);
179 }
180 const uint8_t* fPtr;
181 int fOffset;
182};
183
184template <> struct SkMask::AlphaIter<SkMask::kA8_Format> {
185 AlphaIter(const uint8_t* ptr) : fPtr(ptr) {}
186 AlphaIter(const AlphaIter& that) : fPtr(that.fPtr) {}
187 AlphaIter& operator++() { ++fPtr; return *this; }
188 AlphaIter& operator--() { --fPtr; return *this; }
189 AlphaIter& operator>>=(uint32_t rb) {
190 fPtr = SkTAddOffset<const uint8_t>(fPtr, rb);
191 return *this;
192 }
193 uint8_t operator*() const { return *fPtr; }
194 bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
195 const uint8_t* fPtr;
196};
197
198template <> struct SkMask::AlphaIter<SkMask::kARGB32_Format> {
199 AlphaIter(const uint32_t* ptr) : fPtr(ptr) {}
200 AlphaIter(const AlphaIter& that) : fPtr(that.fPtr) {}
201 AlphaIter& operator++() { ++fPtr; return *this; }
202 AlphaIter& operator--() { --fPtr; return *this; }
203 AlphaIter& operator>>=(uint32_t rb) {
204 fPtr = SkTAddOffset<const uint32_t>(fPtr, rb);
205 return *this;
206 }
207 uint8_t operator*() const { return SkGetPackedA32(*fPtr); }
208 bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
209 const uint32_t* fPtr;
210};
211
212template <> struct SkMask::AlphaIter<SkMask::kLCD16_Format> {
213 AlphaIter(const uint16_t* ptr) : fPtr(ptr) {}
214 AlphaIter(const AlphaIter& that) : fPtr(that.fPtr) {}
215 AlphaIter& operator++() { ++fPtr; return *this; }
216 AlphaIter& operator--() { --fPtr; return *this; }
217 AlphaIter& operator>>=(uint32_t rb) {
218 fPtr = SkTAddOffset<const uint16_t>(fPtr, rb);
219 return *this;
220 }
221 uint8_t operator*() const {
222 unsigned packed = *fPtr;
223 unsigned r = SkPacked16ToR32(packed);
224 unsigned g = SkPacked16ToG32(packed);
225 unsigned b = SkPacked16ToB32(packed);
226 return (r + g + b) / 3;
227 }
228 bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
229 const uint16_t* fPtr;
230};
231
232///////////////////////////////////////////////////////////////////////////////
233
234/**
235 * \using SkAutoMaskImage
236 *
237 * Stack class used to manage the fImage buffer in a SkMask.
238 * When this object loses scope, the buffer is freed with SkMask::FreeImage().
239 */
240using SkAutoMaskFreeImage = std::unique_ptr<uint8_t, SkFunctionWrapper<decltype(SkMask::FreeImage), SkMask::FreeImage>>;
241#define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
242
243#endif
244