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