Home | History | Annotate | Download | only in codec
      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      */
     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      */
     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      */
     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      */
    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      */
    193     void setDstRow(void* dst) { fDstRow = dst; }
    194 
    195     /**
    196      *  Get the next destination row to decode to
    197      */
    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