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*/
19struct SkMask {
20    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     */
41    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    */
59    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    */
70    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     */
82    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     */
95    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 */
135class SkAutoMaskFreeImage {
136public:
137    SkAutoMaskFreeImage(uint8_t* maskImage) {
138        fImage = maskImage;
139    }
140
141    ~SkAutoMaskFreeImage() {
142        SkMask::FreeImage(fImage);
143    }
144
145private:
146    uint8_t* fImage;
147};
148#define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
149
150#endif
151