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