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/base/SkMacros.h" 14 #include "include/private/base/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 */ 22 struct SkMask { SkMaskSkMask23 SkMask() : fImage(nullptr) {} 24 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 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 IsValidFormatSkMask43 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 */ isEmptySkMask47 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 */ getAddr1SkMask65 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 */ getAddr8SkMask76 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 */ getAddrLCD16SkMask88 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 */ getAddr32SkMask101 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 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++() { 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 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); 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 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); 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 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); 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 */ 240 using SkAutoMaskFreeImage = 241 std::unique_ptr<uint8_t, SkFunctionObject<SkMask::FreeImage>>; 242 243 #endif 244