|  | /* | 
|  | * 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 |