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