aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkSwizzler.h
blob: b00ee14e0699189f9834ccc7624ef8ee8924c0f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkSwizzler_DEFINED
#define SkSwizzler_DEFINED

#include "SkCodec.h"
#include "SkColor.h"
#include "SkImageInfo.h"

class SkSwizzler : public SkNoncopyable {
public:
    /**
     *  Enum describing the config of the source data.
     */
    enum SrcConfig {
        kUnknown,  // Invalid type.
        kGray,
        kIndex1,
        kIndex2,
        kIndex4,
        kIndex,
        kRGB,
        kBGR,
        kRGBX,
        kBGRX,
        kRGBA,
        kBGRA,
        kRGB_565,
    };

    /*
     *
     * Result code for the alpha components of a row.
     *
     */
    typedef uint16_t ResultAlpha;
    static const ResultAlpha kOpaque_ResultAlpha = 0xFFFF;
    static const ResultAlpha kTransparent_ResultAlpha = 0x0000;

    /*
     *
     * Checks if the result of decoding a row indicates that the row was
     * transparent.
     *
     */
    static bool IsTransparent(ResultAlpha r) {
        return kTransparent_ResultAlpha == r;
    }

    /*
     *
     * Checks if the result of decoding a row indicates that the row was
     * opaque.
     *
     */
    static bool IsOpaque(ResultAlpha r) {
        return kOpaque_ResultAlpha == r;
    }

    /*
     *
     * Constructs the proper result code based on accumulated alpha masks
     *
     */
    static ResultAlpha GetResult(uint8_t zeroAlpha, uint8_t maxAlpha);

    /*
     *
     * Returns bits per pixel for source config
     *
     */
    static int BitsPerPixel(SrcConfig sc) {
        switch (sc) {
            case kIndex1:
                return 1;
            case kIndex2:
                return 2;
            case kIndex4:
                return 4;
            case kGray:
            case kIndex:
                return 8;
            case kRGB_565:
                return 16;
            case kRGB:
            case kBGR:
                return 24;
            case kRGBX:
            case kRGBA:
            case kBGRX:
            case kBGRA:
                return 32;
            default:
                SkASSERT(false);
                return 0;
        }
    }

    /*
     *
     * Returns bytes per pixel for source config
     * Raises an error if each pixel is not stored in an even number of bytes
     *
     */
    static int BytesPerPixel(SrcConfig sc) {
        SkASSERT(SkIsAlign8(BitsPerPixel(sc)));
        return BitsPerPixel(sc) >> 3;
    }

    /**
     *  Create a new SkSwizzler.
     *  @param SrcConfig Description of the format of the source.
     *  @param SkImageInfo dimensions() describe both the src and the dst.
     *              Other fields describe the dst.
     *  @param dst Destination to write pixels. Must match info and dstRowBytes
     *  @param dstRowBytes rowBytes for dst.
     *  @param ZeroInitialized Whether dst is zero-initialized. The
                               implementation may choose to skip writing zeroes
     *                         if set to kYes_ZeroInitialized.
     *  @return A new SkSwizzler or NULL on failure.
     */
    static SkSwizzler* CreateSwizzler(SrcConfig, const SkPMColor* ctable,
                                      const SkImageInfo&, void* dst,
                                      size_t dstRowBytes,
                                      SkCodec::ZeroInitialized);

    /**
     * Fill the remainder of the destination with a single color
     *
     * @param dstStartRow
     * The destination row to fill from.
     *
     * @param numRows
     * The number of rows to fill.
     *
     * @param colorOrIndex
     * @param colorTable
     * If dstInfo.colorType() is kIndex8, colorOrIndex is assumed to be a uint8_t
     * index, and colorTable is ignored. Each 8-bit pixel will be set to (uint8_t)
     * index.
     *
     * If dstInfo.colorType() is kN32, colorOrIndex is treated differently depending on
     * whether colorTable is NULL:
     *
     * A NULL colorTable means colorOrIndex is treated as an SkPMColor (premul or
     * unpremul, depending on dstInfo.alphaType()). Each 4-byte pixel will be set to
     * colorOrIndex.

     * A non-NULL colorTable means colorOrIndex is treated as a uint8_t index into
     * the colorTable. i.e. each 4-byte pixel will be set to
     * colorTable[(uint8_t) colorOrIndex].
     *
     * If dstInfo.colorType() is kGray, colorOrIndex is always treated as an 8-bit color.
     *
     * Other SkColorTypes are not supported.
     *
     */
    static void Fill(void* dstStartRow, const SkImageInfo& dstInfo, size_t dstRowBytes,
            uint32_t numRows, uint32_t colorOrIndex, const SkPMColor* colorTable);

    /**
     *  Swizzle the next line. Call height times, once for each row of source.
     *  @param src The next row of the source data.
     *  @return A result code describing if the row was fully opaque, fully
     *          transparent, or neither
     */
    ResultAlpha next(const uint8_t* SK_RESTRICT src);

    /**
     *
     * Alternate version of next that allows the caller to specify the row.
     * It is very important to only use one version of next.  Since the other
     * version modifies the dst pointer, it will change the behavior of this
     * function.  We will check this in Debug mode.
     *
     */
    ResultAlpha next(const uint8_t* SK_RESTRICT src, int y);

    /**
     *  Update the destination row.
     *
     *  Typically this is done by next, but for a client that wants to manually
     *  modify the destination row (for example, for decoding scanline one at a
     *  time) they can call this before each call to next.
     *  TODO: Maybe replace this with a version of next which allows supplying the
     *  destination?
     */
    void setDstRow(void* dst) { fDstRow = dst; }

    /**
     *  Get the next destination row to decode to
     */
    void* getDstRow() {
        // kDesignateRow_NextMode does not update the fDstRow ptr.  This function is
        // unnecessary in that case since fDstRow will always be equal to the pointer
        // passed to CreateSwizzler().
        SkASSERT(kDesignateRow_NextMode != fNextMode);
        return fDstRow;
    }

private:

#ifdef SK_DEBUG
    /*
     *
     * Keep track of which version of next the caller is using
     *
     */
    enum NextMode {
        kUninitialized_NextMode,
        kConsecutive_NextMode,
        kDesignateRow_NextMode,
    };

    NextMode fNextMode;
#endif

    /**
     *  Method for converting raw data to Skia pixels.
     *  @param dstRow Row in which to write the resulting pixels.
     *  @param src Row of src data, in format specified by SrcConfig
     *  @param width Width in pixels
     *  @param deltaSrc if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel
     *                  else, deltaSrc is bitsPerPixel
     *  @param y Line of source.
     *  @param ctable Colors (used for kIndex source).
     */
    typedef ResultAlpha (*RowProc)(void* SK_RESTRICT dstRow,
                                   const uint8_t* SK_RESTRICT src,
                                   int width, int deltaSrc, int y,
                                   const SkPMColor ctable[]);

    const RowProc       fRowProc;
    const SkPMColor*    fColorTable;      // Unowned pointer
    const int           fDeltaSrc;        // if bitsPerPixel % 8 == 0
                                          //     deltaSrc is bytesPerPixel
                                          // else
                                          //     deltaSrc is bitsPerPixel
    const SkImageInfo   fDstInfo;
    void*               fDstRow;
    const size_t        fDstRowBytes;
    int                 fCurrY;

    SkSwizzler(RowProc proc, const SkPMColor* ctable, int deltaSrc,
               const SkImageInfo& info, void* dst, size_t rowBytes);

};
#endif // SkSwizzler_DEFINED