blob: 7f5bbc6209b459ceb38fe217319d3759777c2f9a [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
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
scroggo95526622015-03-17 05:02:17 -070011#include "SkCodec.h"
scroggof24f2242015-03-03 08:59:20 -080012#include "SkColor.h"
13#include "SkImageInfo.h"
scroggoe7fc14b2015-10-02 13:14:46 -070014#include "SkSampler.h"
scroggof24f2242015-03-03 08:59:20 -080015
scroggoe7fc14b2015-10-02 13:14:46 -070016class SkSwizzler : public SkSampler {
scroggof24f2242015-03-03 08:59:20 -080017public:
18 /**
19 * Enum describing the config of the source data.
20 */
21 enum SrcConfig {
scroggo05245902015-03-25 11:11:52 -070022 kUnknown, // Invalid type.
msarett99f567e2015-08-05 12:58:26 -070023 kBit, // A single bit to distinguish between white and black
msarett74114382015-03-16 11:55:18 -070024 kGray,
25 kIndex1,
26 kIndex2,
27 kIndex4,
28 kIndex,
29 kRGB,
30 kBGR,
31 kRGBX,
32 kBGRX,
33 kRGBA,
34 kBGRA,
35 kRGB_565,
scroggoef27d892015-10-23 09:29:22 -070036 kCMYK,
scroggof24f2242015-03-03 08:59:20 -080037 };
38
msarett74114382015-03-16 11:55:18 -070039 /*
40 *
41 * Result code for the alpha components of a row.
42 *
43 */
44 typedef uint16_t ResultAlpha;
45 static const ResultAlpha kOpaque_ResultAlpha = 0xFFFF;
46 static const ResultAlpha kTransparent_ResultAlpha = 0x0000;
47
48 /*
49 *
50 * Checks if the result of decoding a row indicates that the row was
51 * transparent.
52 *
53 */
54 static bool IsTransparent(ResultAlpha r) {
55 return kTransparent_ResultAlpha == r;
56 }
57
58 /*
59 *
60 * Checks if the result of decoding a row indicates that the row was
61 * opaque.
62 *
63 */
64 static bool IsOpaque(ResultAlpha r) {
65 return kOpaque_ResultAlpha == r;
66 }
msarett438b2ad2015-04-09 12:43:10 -070067
msarett74114382015-03-16 11:55:18 -070068 /*
69 *
70 * Constructs the proper result code based on accumulated alpha masks
71 *
72 */
73 static ResultAlpha GetResult(uint8_t zeroAlpha, uint8_t maxAlpha);
74
75 /*
76 *
77 * Returns bits per pixel for source config
78 *
79 */
80 static int BitsPerPixel(SrcConfig sc) {
scroggof24f2242015-03-03 08:59:20 -080081 switch (sc) {
msarett99f567e2015-08-05 12:58:26 -070082 case kBit:
msarett74114382015-03-16 11:55:18 -070083 case kIndex1:
84 return 1;
85 case kIndex2:
86 return 2;
87 case kIndex4:
88 return 4;
scroggof24f2242015-03-03 08:59:20 -080089 case kGray:
90 case kIndex:
msarett74114382015-03-16 11:55:18 -070091 return 8;
92 case kRGB_565:
93 return 16;
scroggof24f2242015-03-03 08:59:20 -080094 case kRGB:
msarett74114382015-03-16 11:55:18 -070095 case kBGR:
96 return 24;
scroggof24f2242015-03-03 08:59:20 -080097 case kRGBX:
98 case kRGBA:
msarett74114382015-03-16 11:55:18 -070099 case kBGRX:
100 case kBGRA:
scroggoef27d892015-10-23 09:29:22 -0700101 case kCMYK:
msarett74114382015-03-16 11:55:18 -0700102 return 32;
scroggof24f2242015-03-03 08:59:20 -0800103 default:
msarett74114382015-03-16 11:55:18 -0700104 SkASSERT(false);
105 return 0;
scroggof24f2242015-03-03 08:59:20 -0800106 }
107 }
108
msarett74114382015-03-16 11:55:18 -0700109 /*
110 *
111 * Returns bytes per pixel for source config
112 * Raises an error if each pixel is not stored in an even number of bytes
113 *
114 */
115 static int BytesPerPixel(SrcConfig sc) {
116 SkASSERT(SkIsAlign8(BitsPerPixel(sc)));
117 return BitsPerPixel(sc) >> 3;
118 }
119
scroggof24f2242015-03-03 08:59:20 -0800120 /**
121 * Create a new SkSwizzler.
scroggo95526622015-03-17 05:02:17 -0700122 * @param SrcConfig Description of the format of the source.
scroggoe7fc14b2015-10-02 13:14:46 -0700123 * @param ctable Unowned pointer to an array of up to 256 colors for an
124 * index source.
125 * @param dstInfo Describes the destination.
msarettfdb47572015-10-13 12:50:14 -0700126 * @param options Indicates if dst is zero-initialized. The
scroggoe7fc14b2015-10-02 13:14:46 -0700127 * implementation may choose to skip writing zeroes
scroggo95526622015-03-17 05:02:17 -0700128 * if set to kYes_ZeroInitialized.
msarett5af4e0b2015-11-17 11:18:03 -0800129 * Contains partial scanline information.
130 * @param frame Is non-NULL if the source pixels are part of an image
131 * frame that is a subset of the full image.
132 *
133 * Note that a deeper discussion of partial scanline subsets and image frame
134 * subsets is below. Currently, we do not support both simultaneously. If
135 * options->fSubset is non-NULL, frame must be NULL.
136 *
halcanary96fcdcc2015-08-27 07:41:13 -0700137 * @return A new SkSwizzler or nullptr on failure.
scroggof24f2242015-03-03 08:59:20 -0800138 */
scroggo95526622015-03-17 05:02:17 -0700139 static SkSwizzler* CreateSwizzler(SrcConfig, const SkPMColor* ctable,
msarett5af4e0b2015-11-17 11:18:03 -0800140 const SkImageInfo& dstInfo, const SkCodec::Options&,
141 const SkIRect* frame = nullptr);
scroggoe7fc14b2015-10-02 13:14:46 -0700142
msarett438b2ad2015-04-09 12:43:10 -0700143 /**
msarett614aa072015-07-27 15:13:17 -0700144 * Swizzle a line. Generally this will be called height times, once
145 * for each row of source.
146 * By allowing the caller to pass in the dst pointer, we give the caller
147 * flexibility to use the swizzler even when the encoded data does not
148 * store the rows in order. This also improves usability for scaled and
149 * subset decodes.
150 * @param dst Where we write the output.
scroggof24f2242015-03-03 08:59:20 -0800151 * @param src The next row of the source data.
msarett74114382015-03-16 11:55:18 -0700152 * @return A result code describing if the row was fully opaque, fully
153 * transparent, or neither
scroggof24f2242015-03-03 08:59:20 -0800154 */
msarett614aa072015-07-27 15:13:17 -0700155 ResultAlpha swizzle(void* dst, const uint8_t* SK_RESTRICT src);
msarett3c309db2015-04-10 14:36:48 -0700156
msarette6dd0042015-10-09 11:07:34 -0700157 /**
158 * Implement fill using a custom width.
159 */
160 void fill(const SkImageInfo& info, void* dst, size_t rowBytes, uint32_t colorOrIndex,
161 SkCodec::ZeroInitialized zeroInit) override {
msarett5af4e0b2015-11-17 11:18:03 -0800162 const SkImageInfo fillInfo = info.makeWH(fAllocatedWidth, info.height());
msarette6dd0042015-10-09 11:07:34 -0700163 SkSampler::Fill(fillInfo, dst, rowBytes, colorOrIndex, zeroInit);
164 }
165
scroggof24f2242015-03-03 08:59:20 -0800166private:
msarett74114382015-03-16 11:55:18 -0700167
scroggof24f2242015-03-03 08:59:20 -0800168 /**
169 * Method for converting raw data to Skia pixels.
170 * @param dstRow Row in which to write the resulting pixels.
171 * @param src Row of src data, in format specified by SrcConfig
emmaleer8f4ba762015-08-14 07:44:46 -0700172 * @param dstWidth Width in pixels of the destination
msarett5406d6f2015-08-31 06:55:13 -0700173 * @param bpp if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel
174 * else, deltaSrc is bitsPerPixel
175 * @param deltaSrc bpp * sampleX
scroggof24f2242015-03-03 08:59:20 -0800176 * @param ctable Colors (used for kIndex source).
emmaleer8f4ba762015-08-14 07:44:46 -0700177 * @param offset The offset before the first pixel to sample.
178 Is in bytes or bits based on what deltaSrc is in.
scroggof24f2242015-03-03 08:59:20 -0800179 */
msarett74114382015-03-16 11:55:18 -0700180 typedef ResultAlpha (*RowProc)(void* SK_RESTRICT dstRow,
181 const uint8_t* SK_RESTRICT src,
msarett5406d6f2015-08-31 06:55:13 -0700182 int dstWidth, int bpp, int deltaSrc, int offset,
msarett74114382015-03-16 11:55:18 -0700183 const SkPMColor ctable[]);
scroggof24f2242015-03-03 08:59:20 -0800184
185 const RowProc fRowProc;
msarett74114382015-03-16 11:55:18 -0700186 const SkPMColor* fColorTable; // Unowned pointer
msarett5af4e0b2015-11-17 11:18:03 -0800187
188 // Subset Swizzles
189 // There are two types of subset swizzles that we support. We do not
190 // support both at the same time.
191 // TODO: If we want to support partial scanlines for gifs (which may
192 // use frame subsets), we will need to support both subsetting
193 // modes at the same time.
194 // (1) Partial Scanlines
195 // The client only wants to write a subset of the source pixels
196 // to the destination. This subset is specified to CreateSwizzler
197 // using options->fSubset. We will store subset information in
198 // the following fields.
199 //
200 // fSrcOffset: The starting pixel of the source.
201 // fSrcOffsetUnits: Derived from fSrcOffset with two key
202 // differences:
203 // (1) This takes the size of source pixels into
204 // account by multiplying by fSrcBPP. This may
205 // be measured in bits or bytes depending on
206 // which is natural for the SrcConfig.
207 // (2) If we are sampling, this will be larger
208 // than fSrcOffset * fSrcBPP, since sampling
209 // implies that we will skip some pixels.
210 // fDstOffset: Will be zero. There is no destination offset
211 // for this type of subset.
212 // fDstOffsetBytes: Will be zero.
213 // fSrcWidth: The width of the desired subset of source
214 // pixels, before any sampling is performed.
215 // fDstWidth: Will be equal to fSrcWidth, since this is also
216 // calculated before any sampling is performed.
217 // For this type of subset, the destination width
218 // matches the desired subset of the source.
219 // fSwizzleWidth: The actual number of pixels that will be
220 // written by the RowProc. This is a scaled
221 // version of fSrcWidth/fDstWidth.
222 // fAllocatedWidth: Will be equal to fSwizzleWidth. For this type
223 // of subset, the number of pixels written is the
224 // same as the actual width of the destination.
225 // (2) Frame Subset
226 // The client will decode the entire width of the source into a
227 // subset of destination memory. This subset is specified to
228 // CreateSwizzler in the "frame" parameter. We store subset
229 // information in the following fields.
230 //
231 // fSrcOffset: Will be zero. The starting pixel of the source.
232 // fSrcOffsetUnits: Will only be non-zero if we are sampling,
233 // since sampling implies that we will skip some
234 // pixels. Note that this is measured in bits
235 // or bytes depending on which is natural for
236 // SrcConfig.
237 // fDstOffset: First pixel to write in destination.
238 // fDstOffsetBytes: fDstOffset * fDstBPP.
239 // fSrcWidth: The entire width of the source pixels, before
240 // any sampling is performed.
241 // fDstWidth: The entire width of the destination memory,
242 // before any sampling is performed.
243 // fSwizzleWidth: The actual number of pixels that will be
244 // written by the RowProc. This is a scaled
245 // version of fSrcWidth.
246 // fAllocatedWidth: The actual number of pixels in destination
247 // memory. This is a scaled version of
248 // fDstWidth.
249 //
250 // If we are not subsetting, these fields are more straightforward.
251 // fSrcOffset = fDstOffet = fDstOffsetBytes = 0
252 // fSrcOffsetUnits may be non-zero (we will skip the first few pixels when sampling)
253 // fSrcWidth = fDstWidth = Full original width
254 // fSwizzleWidth = fAllcoatedWidth = Scaled width (if we are sampling)
255 const int fSrcOffset;
256 const int fDstOffset;
257 int fSrcOffsetUnits;
258 int fDstOffsetBytes;
259 const int fSrcWidth;
260 const int fDstWidth;
261 int fSwizzleWidth;
262 int fAllocatedWidth;
263
264 int fSampleX; // Step between X samples
265 const int fSrcBPP; // Bits/bytes per pixel for the SrcConfig
266 // if bitsPerPixel % 8 == 0
msarettfdb47572015-10-13 12:50:14 -0700267 // fBPP is bytesPerPixel
268 // else
269 // fBPP is bitsPerPixel
msarett5af4e0b2015-11-17 11:18:03 -0800270 const int fDstBPP; // Bytes per pixel for the destination color type
scroggof24f2242015-03-03 08:59:20 -0800271
msarett5af4e0b2015-11-17 11:18:03 -0800272 SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcOffset, int srcWidth, int dstOffset,
273 int dstWidth, int srcBPP, int dstBPP);
scroggoe7fc14b2015-10-02 13:14:46 -0700274
275 int onSetSampleX(int) override;
msarette6dd0042015-10-09 11:07:34 -0700276
scroggof24f2242015-03-03 08:59:20 -0800277};
278#endif // SkSwizzler_DEFINED