/* * 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, SkImageGenerator::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