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 #include "SkSampler.h" 15 16 class SkSwizzler : public SkSampler { 17 public: 18 /** 19 * Create a new SkSwizzler. 20 * @param encodedInfo Description of the format of the encoded data. 21 * @param ctable Unowned pointer to an array of up to 256 colors for an 22 * index source. 23 * @param dstInfo Describes the destination. 24 * @param options Indicates if dst is zero-initialized. The 25 * implementation may choose to skip writing zeroes 26 * if set to kYes_ZeroInitialized. 27 * Contains partial scanline information. 28 * @param frame Is non-NULL if the source pixels are part of an image 29 * frame that is a subset of the full image. 30 * @param skipFormatConversion Indicates that we should skip format conversion. 31 * The swizzler only needs to sample and/or subset. 32 * 33 * Note that a deeper discussion of partial scanline subsets and image frame 34 * subsets is below. Currently, we do not support both simultaneously. If 35 * options->fSubset is non-NULL, frame must be NULL. 36 * 37 * @return A new SkSwizzler or nullptr on failure. 38 */ 39 static SkSwizzler* CreateSwizzler(const SkEncodedInfo& encodedInfo, const SkPMColor* ctable, 40 const SkImageInfo& dstInfo, const SkCodec::Options&, 41 const SkIRect* frame = nullptr, 42 bool skipFormatConversion = false); 43 44 /** 45 * Swizzle a line. Generally this will be called height times, once 46 * for each row of source. 47 * By allowing the caller to pass in the dst pointer, we give the caller 48 * flexibility to use the swizzler even when the encoded data does not 49 * store the rows in order. This also improves usability for scaled and 50 * subset decodes. 51 * @param dst Where we write the output. 52 * @param src The next row of the source data. 53 */ 54 void swizzle(void* dst, const uint8_t* SK_RESTRICT src); 55 56 /** 57 * Implement fill using a custom width. 58 */ fill(const SkImageInfo & info,void * dst,size_t rowBytes,uint64_t colorOrIndex,SkCodec::ZeroInitialized zeroInit)59 void fill(const SkImageInfo& info, void* dst, size_t rowBytes, uint64_t colorOrIndex, 60 SkCodec::ZeroInitialized zeroInit) override { 61 const SkImageInfo fillInfo = info.makeWH(fAllocatedWidth, info.height()); 62 SkSampler::Fill(fillInfo, dst, rowBytes, colorOrIndex, zeroInit); 63 } 64 65 /** 66 * If fSampleX > 1, the swizzler is sampling every fSampleX'th pixel and 67 * discarding the rest. 68 * 69 * This getter is currently used by SkBmpStandardCodec for Bmp-in-Ico decodes. 70 * Ideally, the subclasses of SkCodec would have no knowledge of sampling, but 71 * this allows us to apply a transparency mask to pixels after swizzling. 72 */ sampleX()73 int sampleX() const { return fSampleX; } 74 75 /** 76 * Returns the actual number of pixels written to destination memory, taking 77 * scaling, subsetting, and partial frames into account. 78 */ swizzleWidth()79 int swizzleWidth() const { return fSwizzleWidth; } 80 81 /** 82 * Returns the byte offset at which we write to destination memory, taking 83 * scaling, subsetting, and partial frames into account. 84 */ swizzleOffsetBytes()85 size_t swizzleOffsetBytes() const { return fDstOffsetBytes; } 86 87 private: 88 89 /** 90 * Method for converting raw data to Skia pixels. 91 * @param dstRow Row in which to write the resulting pixels. 92 * @param src Row of src data, in format specified by SrcConfig 93 * @param dstWidth Width in pixels of the destination 94 * @param bpp if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel 95 * else, deltaSrc is bitsPerPixel 96 * @param deltaSrc bpp * sampleX 97 * @param ctable Colors (used for kIndex source). 98 * @param offset The offset before the first pixel to sample. 99 Is in bytes or bits based on what deltaSrc is in. 100 */ 101 typedef void (*RowProc)(void* SK_RESTRICT dstRow, 102 const uint8_t* SK_RESTRICT src, 103 int dstWidth, int bpp, int deltaSrc, int offset, 104 const SkPMColor ctable[]); 105 106 template <RowProc Proc> 107 static void SkipLeading8888ZerosThen(void* SK_RESTRICT dstRow, 108 const uint8_t* SK_RESTRICT src, 109 int dstWidth, int bpp, int deltaSrc, int offset, 110 const SkPMColor ctable[]); 111 112 template <RowProc Proc> 113 static void SkipLeadingGrayAlphaZerosThen(void* dst, const uint8_t* src, int width, int bpp, 114 int deltaSrc, int offset, const SkPMColor ctable[]); 115 116 // May be NULL. We have not implemented optimized functions for all supported transforms. 117 const RowProc fFastProc; 118 // Always non-NULL. Supports sampling. 119 const RowProc fSlowProc; 120 // The actual RowProc we are using. This depends on if fFastProc is non-NULL and 121 // whether or not we are sampling. 122 RowProc fActualProc; 123 124 const SkPMColor* fColorTable; // Unowned pointer 125 126 // Subset Swizzles 127 // There are two types of subset swizzles that we support. We do not 128 // support both at the same time. 129 // TODO: If we want to support partial scanlines for gifs (which may 130 // use frame subsets), we will need to support both subsetting 131 // modes at the same time. 132 // (1) Partial Scanlines 133 // The client only wants to write a subset of the source pixels 134 // to the destination. This subset is specified to CreateSwizzler 135 // using options->fSubset. We will store subset information in 136 // the following fields. 137 // 138 // fSrcOffset: The starting pixel of the source. 139 // fSrcOffsetUnits: Derived from fSrcOffset with two key 140 // differences: 141 // (1) This takes the size of source pixels into 142 // account by multiplying by fSrcBPP. This may 143 // be measured in bits or bytes depending on 144 // which is natural for the SrcConfig. 145 // (2) If we are sampling, this will be larger 146 // than fSrcOffset * fSrcBPP, since sampling 147 // implies that we will skip some pixels. 148 // fDstOffset: Will be zero. There is no destination offset 149 // for this type of subset. 150 // fDstOffsetBytes: Will be zero. 151 // fSrcWidth: The width of the desired subset of source 152 // pixels, before any sampling is performed. 153 // fDstWidth: Will be equal to fSrcWidth, since this is also 154 // calculated before any sampling is performed. 155 // For this type of subset, the destination width 156 // matches the desired subset of the source. 157 // fSwizzleWidth: The actual number of pixels that will be 158 // written by the RowProc. This is a scaled 159 // version of fSrcWidth/fDstWidth. 160 // fAllocatedWidth: Will be equal to fSwizzleWidth. For this type 161 // of subset, the number of pixels written is the 162 // same as the actual width of the destination. 163 // (2) Frame Subset 164 // The client will decode the entire width of the source into a 165 // subset of destination memory. This subset is specified to 166 // CreateSwizzler in the "frame" parameter. We store subset 167 // information in the following fields. 168 // 169 // fSrcOffset: Will be zero. The starting pixel of the source. 170 // fSrcOffsetUnits: Will only be non-zero if we are sampling, 171 // since sampling implies that we will skip some 172 // pixels. Note that this is measured in bits 173 // or bytes depending on which is natural for 174 // SrcConfig. 175 // fDstOffset: First pixel to write in destination. 176 // fDstOffsetBytes: fDstOffset * fDstBPP. 177 // fSrcWidth: The entire width of the source pixels, before 178 // any sampling is performed. 179 // fDstWidth: The entire width of the destination memory, 180 // before any sampling is performed. 181 // fSwizzleWidth: The actual number of pixels that will be 182 // written by the RowProc. This is a scaled 183 // version of fSrcWidth. 184 // fAllocatedWidth: The actual number of pixels in destination 185 // memory. This is a scaled version of 186 // fDstWidth. 187 // 188 // If we are not subsetting, these fields are more straightforward. 189 // fSrcOffset = fDstOffet = fDstOffsetBytes = 0 190 // fSrcOffsetUnits may be non-zero (we will skip the first few pixels when sampling) 191 // fSrcWidth = fDstWidth = Full original width 192 // fSwizzleWidth = fAllcoatedWidth = Scaled width (if we are sampling) 193 const int fSrcOffset; 194 const int fDstOffset; 195 int fSrcOffsetUnits; 196 int fDstOffsetBytes; 197 const int fSrcWidth; 198 const int fDstWidth; 199 int fSwizzleWidth; 200 int fAllocatedWidth; 201 202 int fSampleX; // Step between X samples 203 const int fSrcBPP; // Bits/bytes per pixel for the SrcConfig 204 // if bitsPerPixel % 8 == 0 205 // fBPP is bytesPerPixel 206 // else 207 // fBPP is bitsPerPixel 208 const int fDstBPP; // Bytes per pixel for the destination color type 209 210 SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset, 211 int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP); 212 213 int onSetSampleX(int) override; 214 215 }; 216 #endif // SkSwizzler_DEFINED 217