1 /*
2  * Copyright 2015 Google Inc.
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 SkSwizzler_DEFINED
9 #define SkSwizzler_DEFINED
10 
11 #include "SkCodec.h"
12 #include "SkColor.h"
13 #include "SkImageInfo.h"
14 
15 class SkSwizzler : public SkNoncopyable {
16 public:
17     /**
18      *  Enum describing the config of the source data.
19      */
20     enum SrcConfig {
21         kUnknown,  // Invalid type.
22         kGray,
23         kIndex1,
24         kIndex2,
25         kIndex4,
26         kIndex,
27         kRGB,
28         kBGR,
29         kRGBX,
30         kBGRX,
31         kRGBA,
32         kBGRA,
33         kRGB_565,
34     };
35 
36     /*
37      *
38      * Result code for the alpha components of a row.
39      *
40      */
41     typedef uint16_t ResultAlpha;
42     static const ResultAlpha kOpaque_ResultAlpha = 0xFFFF;
43     static const ResultAlpha kTransparent_ResultAlpha = 0x0000;
44 
45     /*
46      *
47      * Checks if the result of decoding a row indicates that the row was
48      * transparent.
49      *
50      */
IsTransparent(ResultAlpha r)51     static bool IsTransparent(ResultAlpha r) {
52         return kTransparent_ResultAlpha == r;
53     }
54 
55     /*
56      *
57      * Checks if the result of decoding a row indicates that the row was
58      * opaque.
59      *
60      */
IsOpaque(ResultAlpha r)61     static bool IsOpaque(ResultAlpha r) {
62         return kOpaque_ResultAlpha == r;
63     }
64 
65     /*
66      *
67      * Constructs the proper result code based on accumulated alpha masks
68      *
69      */
70     static ResultAlpha GetResult(uint8_t zeroAlpha, uint8_t maxAlpha);
71 
72     /*
73      *
74      * Returns bits per pixel for source config
75      *
76      */
BitsPerPixel(SrcConfig sc)77     static int BitsPerPixel(SrcConfig sc) {
78         switch (sc) {
79             case kIndex1:
80                 return 1;
81             case kIndex2:
82                 return 2;
83             case kIndex4:
84                 return 4;
85             case kGray:
86             case kIndex:
87                 return 8;
88             case kRGB_565:
89                 return 16;
90             case kRGB:
91             case kBGR:
92                 return 24;
93             case kRGBX:
94             case kRGBA:
95             case kBGRX:
96             case kBGRA:
97                 return 32;
98             default:
99                 SkASSERT(false);
100                 return 0;
101         }
102     }
103 
104     /*
105      *
106      * Returns bytes per pixel for source config
107      * Raises an error if each pixel is not stored in an even number of bytes
108      *
109      */
BytesPerPixel(SrcConfig sc)110     static int BytesPerPixel(SrcConfig sc) {
111         SkASSERT(SkIsAlign8(BitsPerPixel(sc)));
112         return BitsPerPixel(sc) >> 3;
113     }
114 
115     /**
116      *  Create a new SkSwizzler.
117      *  @param SrcConfig Description of the format of the source.
118      *  @param SkImageInfo dimensions() describe both the src and the dst.
119      *              Other fields describe the dst.
120      *  @param dst Destination to write pixels. Must match info and dstRowBytes
121      *  @param dstRowBytes rowBytes for dst.
122      *  @param ZeroInitialized Whether dst is zero-initialized. The
123                                implementation may choose to skip writing zeroes
124      *                         if set to kYes_ZeroInitialized.
125      *  @return A new SkSwizzler or NULL on failure.
126      */
127     static SkSwizzler* CreateSwizzler(SrcConfig, const SkPMColor* ctable,
128                                       const SkImageInfo&, void* dst,
129                                       size_t dstRowBytes,
130                                       SkImageGenerator::ZeroInitialized);
131 
132     /**
133      * Fill the remainder of the destination with a single color
134      *
135      * @param dstStartRow
136      * The destination row to fill from.
137      *
138      * @param numRows
139      * The number of rows to fill.
140      *
141      * @param colorOrIndex
142      * @param colorTable
143      * If dstInfo.colorType() is kIndex8, colorOrIndex is assumed to be a uint8_t
144      * index, and colorTable is ignored. Each 8-bit pixel will be set to (uint8_t)
145      * index.
146      *
147      * If dstInfo.colorType() is kN32, colorOrIndex is treated differently depending on
148      * whether colorTable is NULL:
149      *
150      * A NULL colorTable means colorOrIndex is treated as an SkPMColor (premul or
151      * unpremul, depending on dstInfo.alphaType()). Each 4-byte pixel will be set to
152      * colorOrIndex.
153 
154      * A non-NULL colorTable means colorOrIndex is treated as a uint8_t index into
155      * the colorTable. i.e. each 4-byte pixel will be set to
156      * colorTable[(uint8_t) colorOrIndex].
157      *
158      * If dstInfo.colorType() is kGray, colorOrIndex is always treated as an 8-bit color.
159      *
160      * Other SkColorTypes are not supported.
161      *
162      */
163     static void Fill(void* dstStartRow, const SkImageInfo& dstInfo, size_t dstRowBytes,
164             uint32_t numRows, uint32_t colorOrIndex, const SkPMColor* colorTable);
165 
166     /**
167      *  Swizzle the next line. Call height times, once for each row of source.
168      *  @param src The next row of the source data.
169      *  @return A result code describing if the row was fully opaque, fully
170      *          transparent, or neither
171      */
172     ResultAlpha next(const uint8_t* SK_RESTRICT src);
173 
174     /**
175      *
176      * Alternate version of next that allows the caller to specify the row.
177      * It is very important to only use one version of next.  Since the other
178      * version modifies the dst pointer, it will change the behavior of this
179      * function.  We will check this in Debug mode.
180      *
181      */
182     ResultAlpha next(const uint8_t* SK_RESTRICT src, int y);
183 
184     /**
185      *  Update the destination row.
186      *
187      *  Typically this is done by next, but for a client that wants to manually
188      *  modify the destination row (for example, for decoding scanline one at a
189      *  time) they can call this before each call to next.
190      *  TODO: Maybe replace this with a version of next which allows supplying the
191      *  destination?
192      */
setDstRow(void * dst)193     void setDstRow(void* dst) { fDstRow = dst; }
194 
195     /**
196      *  Get the next destination row to decode to
197      */
getDstRow()198     void* getDstRow() {
199         // kDesignateRow_NextMode does not update the fDstRow ptr.  This function is
200         // unnecessary in that case since fDstRow will always be equal to the pointer
201         // passed to CreateSwizzler().
202         SkASSERT(kDesignateRow_NextMode != fNextMode);
203         return fDstRow;
204     }
205 
206 private:
207 
208 #ifdef SK_DEBUG
209     /*
210      *
211      * Keep track of which version of next the caller is using
212      *
213      */
214     enum NextMode {
215         kUninitialized_NextMode,
216         kConsecutive_NextMode,
217         kDesignateRow_NextMode,
218     };
219 
220     NextMode fNextMode;
221 #endif
222 
223     /**
224      *  Method for converting raw data to Skia pixels.
225      *  @param dstRow Row in which to write the resulting pixels.
226      *  @param src Row of src data, in format specified by SrcConfig
227      *  @param width Width in pixels
228      *  @param deltaSrc if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel
229      *                  else, deltaSrc is bitsPerPixel
230      *  @param y Line of source.
231      *  @param ctable Colors (used for kIndex source).
232      */
233     typedef ResultAlpha (*RowProc)(void* SK_RESTRICT dstRow,
234                                    const uint8_t* SK_RESTRICT src,
235                                    int width, int deltaSrc, int y,
236                                    const SkPMColor ctable[]);
237 
238     const RowProc       fRowProc;
239     const SkPMColor*    fColorTable;      // Unowned pointer
240     const int           fDeltaSrc;        // if bitsPerPixel % 8 == 0
241                                           //     deltaSrc is bytesPerPixel
242                                           // else
243                                           //     deltaSrc is bitsPerPixel
244     const SkImageInfo   fDstInfo;
245     void*               fDstRow;
246     const size_t        fDstRowBytes;
247     int                 fCurrY;
248 
249     SkSwizzler(RowProc proc, const SkPMColor* ctable, int deltaSrc,
250                const SkImageInfo& info, void* dst, size_t rowBytes);
251 
252 };
253 #endif // SkSwizzler_DEFINED
254