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