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 */
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 
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 = std::unique_ptr<uint8_t, SkFunctionWrapper<decltype(SkMask::FreeImage), SkMask::FreeImage>>;
241 #define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
242 
243 #endif
244