xref: /third_party/skia/src/core/SkMask.h (revision cb93a386)
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*/
22struct SkMask {
23    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
43    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     */
47    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    */
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;
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    */
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;
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     */
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);
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     */
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);
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
151template <> 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
184template <> 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
198template <> 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
212template <> 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 */
240using SkAutoMaskFreeImage =
241        std::unique_ptr<uint8_t, SkFunctionWrapper<decltype(SkMask::FreeImage), SkMask::FreeImage>>;
242
243#endif
244