1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkMask_DEFINED
11 #define SkMask_DEFINED
12 
13 #include "SkRect.h"
14 
15 /** \class SkMask
16     SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
17     the 3-channel 3D format. These are passed to SkMaskFilter objects.
18 */
19 struct SkMask {
SkMaskSkMask20     SkMask() : fImage(nullptr) {}
21 
22     enum Format {
23         kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
24         kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
25         k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
26         kARGB32_Format,         //!< SkPMColor
27         kLCD16_Format,          //!< 565 alpha for r/g/b
28     };
29 
30     enum {
31         kCountMaskFormats = kLCD16_Format + 1
32     };
33 
34     uint8_t*    fImage;
35     SkIRect     fBounds;
36     uint32_t    fRowBytes;
37     Format      fFormat;
38 
39     /** Returns true if the mask is empty: i.e. it has an empty bounds.
40      */
isEmptySkMask41     bool isEmpty() const { return fBounds.isEmpty(); }
42 
43     /** Return the byte size of the mask, assuming only 1 plane.
44         Does not account for k3D_Format. For that, use computeTotalImageSize().
45         If there is an overflow of 32bits, then returns 0.
46     */
47     size_t computeImageSize() const;
48 
49     /** Return the byte size of the mask, taking into account
50         any extra planes (e.g. k3D_Format).
51         If there is an overflow of 32bits, then returns 0.
52     */
53     size_t computeTotalImageSize() const;
54 
55     /** Returns the address of the byte that holds the specified bit.
56         Asserts that the mask is kBW_Format, and that x,y are in range.
57         x,y are in the same coordiate space as fBounds.
58     */
getAddr1SkMask59     uint8_t* getAddr1(int x, int y) const {
60         SkASSERT(kBW_Format == fFormat);
61         SkASSERT(fBounds.contains(x, y));
62         SkASSERT(fImage != NULL);
63         return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes;
64     }
65 
66     /** Returns the address of the specified byte.
67         Asserts that the mask is kA8_Format, and that x,y are in range.
68         x,y are in the same coordiate space as fBounds.
69     */
getAddr8SkMask70     uint8_t* getAddr8(int x, int y) const {
71         SkASSERT(kA8_Format == fFormat);
72         SkASSERT(fBounds.contains(x, y));
73         SkASSERT(fImage != NULL);
74         return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
75     }
76 
77     /**
78      *  Return the address of the specified 16bit mask. In the debug build,
79      *  this asserts that the mask's format is kLCD16_Format, and that (x,y)
80      *  are contained in the mask's fBounds.
81      */
getAddrLCD16SkMask82     uint16_t* getAddrLCD16(int x, int y) const {
83         SkASSERT(kLCD16_Format == fFormat);
84         SkASSERT(fBounds.contains(x, y));
85         SkASSERT(fImage != NULL);
86         uint16_t* row = (uint16_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
87         return row + (x - fBounds.fLeft);
88     }
89 
90     /**
91      *  Return the address of the specified 32bit mask. In the debug build,
92      *  this asserts that the mask's format is 32bits, and that (x,y)
93      *  are contained in the mask's fBounds.
94      */
getAddr32SkMask95     uint32_t* getAddr32(int x, int y) const {
96         SkASSERT(kARGB32_Format == fFormat);
97         SkASSERT(fBounds.contains(x, y));
98         SkASSERT(fImage != NULL);
99         uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
100         return row + (x - fBounds.fLeft);
101     }
102 
103     /**
104      *  Returns the address of the specified pixel, computing the pixel-size
105      *  at runtime based on the mask format. This will be slightly slower than
106      *  using one of the routines where the format is implied by the name
107      *  e.g. getAddr8 or getAddr32.
108      *
109      *  x,y must be contained by the mask's bounds (this is asserted in the
110      *  debug build, but not checked in the release build.)
111      *
112      *  This should not be called with kBW_Format, as it will give unspecified
113      *  results (and assert in the debug build).
114      */
115     void* getAddr(int x, int y) const;
116 
117     static uint8_t* AllocImage(size_t bytes);
118     static void FreeImage(void* image);
119 
120     enum CreateMode {
121         kJustComputeBounds_CreateMode,      //!< compute bounds and return
122         kJustRenderImage_CreateMode,        //!< render into preallocate mask
123         kComputeBoundsAndRenderImage_CreateMode  //!< compute bounds, alloc image and render into it
124     };
125 };
126 
127 ///////////////////////////////////////////////////////////////////////////////
128 
129 /**
130  *  \class SkAutoMaskImage
131  *
132  *  Stack class used to manage the fImage buffer in a SkMask.
133  *  When this object loses scope, the buffer is freed with SkMask::FreeImage().
134  */
135 class SkAutoMaskFreeImage {
136 public:
SkAutoMaskFreeImage(uint8_t * maskImage)137     SkAutoMaskFreeImage(uint8_t* maskImage) {
138         fImage = maskImage;
139     }
140 
~SkAutoMaskFreeImage()141     ~SkAutoMaskFreeImage() {
142         SkMask::FreeImage(fImage);
143     }
144 
145 private:
146     uint8_t* fImage;
147 };
148 #define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
149 
150 #endif
151