2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "include/core/SkRect.h"
12 #include "include/private/SkColorData.h"
13 #include "include/private/SkMacros.h"
14 #include "include/private/SkTemplates.h"
19 SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
20 the 3-channel 3D format. These are passed to SkMaskFilter objects.
23 SkMask() : fImage(nullptr) {}
25 enum Format : uint8_t {
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
35 kCountMaskFormats = kSDF_Format + 1
43 static bool IsValidFormat(uint8_t format) { return format < kCountMaskFormats; }
45 /** Returns true if the mask is empty: i.e. it has an empty bounds.
47 bool isEmpty() const { return fBounds.isEmpty(); }
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.
53 size_t computeImageSize() const;
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.
59 size_t computeTotalImageSize() const;
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.
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;
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.
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;
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.
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);
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.
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);
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.
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.)
118 * This should not be called with kBW_Format, as it will give unspecified
119 * results (and assert in the debug build).
121 void* getAddr(int x, int y) const;
127 static uint8_t* AllocImage(size_t bytes, AllocType = kUninit_Alloc);
128 static void FreeImage(void* image);
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
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
143 template <Format F> struct AlphaIter;
146 * Returns initial destination mask data padded by radiusX and radiusY
148 static SkMask PrepareDestination(int radiusX, int radiusY, const SkMask& src);
151 template <> 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++() {
163 AlphaIter& operator--() {
172 AlphaIter& operator>>=(uint32_t rb) {
173 fPtr = SkTAddOffset<const uint8_t>(fPtr, rb);
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);
184 template <> 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);
193 uint8_t operator*() const { return *fPtr; }
194 bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
198 template <> 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);
207 uint8_t operator*() const { return SkGetPackedA32(*fPtr); }
208 bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
209 const uint32_t* fPtr;
212 template <> 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);
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;
228 bool operator<(const AlphaIter& that) const { return fPtr < that.fPtr; }
229 const uint16_t* fPtr;
232 ///////////////////////////////////////////////////////////////////////////////
235 * \using SkAutoMaskImage
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().
240 using SkAutoMaskFreeImage =
241 std::unique_ptr<uint8_t, SkFunctionWrapper<decltype(SkMask::FreeImage), SkMask::FreeImage>>;