Flutter Engine
The Flutter Engine
SkBmpRLECodec.cpp
Go to the documentation of this file.
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
9
15#include "include/core/SkSize.h"
23
24#include <algorithm>
25#include <cstring>
26#include <memory>
27#include <utility>
28
29/*
30 * Creates an instance of the decoder
31 * Called only by NewFromStream
32 */
34 std::unique_ptr<SkStream> stream,
35 uint16_t bitsPerPixel, uint32_t numColors,
36 uint32_t bytesPerColor, uint32_t offset,
38 : INHERITED(std::move(info), std::move(stream), bitsPerPixel, rowOrder)
39 , fColorTable(nullptr)
40 , fNumColors(numColors)
41 , fBytesPerColor(bytesPerColor)
42 , fOffset(offset)
43 , fBytesBuffered(0)
44 , fCurrRLEByte(0)
45 , fSampleX(1)
46{}
47
48/*
49 * Initiates the bitmap decode
50 */
52 void* dst, size_t dstRowBytes,
53 const Options& opts,
54 int* rowsDecoded) {
55 if (opts.fSubset) {
56 // Subsets are not supported.
57 return kUnimplemented;
58 }
59
60 Result result = this->prepareToDecode(dstInfo, opts);
61 if (kSuccess != result) {
62 return result;
63 }
64
65 // Perform the decode
66 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
67 if (rows != dstInfo.height()) {
68 // We set rowsDecoded equal to the height because the background has already
69 // been filled. RLE encodings sometimes skip pixels, so we always start by
70 // filling the background.
71 *rowsDecoded = dstInfo.height();
72 return kIncompleteInput;
73 }
74
75 return kSuccess;
76}
77
78/*
79 * Process the color table for the bmp input
80 */
81 bool SkBmpRLECodec::createColorTable(SkColorType dstColorType) {
82 // Allocate memory for color table
83 uint32_t colorBytes = 0;
84 SkPMColor colorTable[256];
85 if (this->bitsPerPixel() <= 8) {
86 // Inform the caller of the number of colors
87 uint32_t maxColors = 1 << this->bitsPerPixel();
88 // Don't bother reading more than maxColors.
89 const uint32_t numColorsToRead =
90 fNumColors == 0 ? maxColors : std::min(fNumColors, maxColors);
91
92 // Read the color table from the stream
93 colorBytes = numColorsToRead * fBytesPerColor;
94 std::unique_ptr<uint8_t[]> cBuffer(new uint8_t[colorBytes]);
95 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
96 SkCodecPrintf("Error: unable to read color table.\n");
97 return false;
98 }
99
100 // Fill in the color table
101 PackColorProc packARGB = choose_pack_color_proc(false, dstColorType);
102 uint32_t i = 0;
103 for (; i < numColorsToRead; i++) {
104 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
105 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
106 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
107 colorTable[i] = packARGB(0xFF, red, green, blue);
108 }
109
110 // To avoid segmentation faults on bad pixel data, fill the end of the
111 // color table with black. This is the same the behavior as the
112 // chromium decoder.
113 for (; i < maxColors; i++) {
114 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
115 }
116
117 // Set the color table
118 fColorTable.reset(new SkColorPalette(colorTable, maxColors));
119 }
120
121 // Check that we have not read past the pixel array offset
122 if(fOffset < colorBytes) {
123 // This may occur on OS 2.1 and other old versions where the color
124 // table defaults to max size, and the bmp tries to use a smaller
125 // color table. This is invalid, and our decision is to indicate
126 // an error, rather than try to guess the intended size of the
127 // color table.
128 SkCodecPrintf("Error: pixel data offset less than color table size.\n");
129 return false;
130 }
131
132 // After reading the color table, skip to the start of the pixel array
133 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
134 SkCodecPrintf("Error: unable to skip to image data.\n");
135 return false;
136 }
137
138 // Return true on success
139 return true;
140}
141
142bool SkBmpRLECodec::initializeStreamBuffer() {
143 fBytesBuffered = this->stream()->read(fStreamBuffer, kBufferSize);
144 if (fBytesBuffered == 0) {
145 SkCodecPrintf("Error: could not read RLE image data.\n");
146 return false;
147 }
148 fCurrRLEByte = 0;
149 return true;
150}
151
152/*
153 * @return the number of bytes remaining in the stream buffer after
154 * attempting to read more bytes from the stream
155 */
156size_t SkBmpRLECodec::checkForMoreData() {
157 const size_t remainingBytes = fBytesBuffered - fCurrRLEByte;
158 uint8_t* buffer = fStreamBuffer;
159
160 // We will be reusing the same buffer, starting over from the beginning.
161 // Move any remaining bytes to the start of the buffer.
162 // We use memmove() instead of memcpy() because there is risk that the dst
163 // and src memory will overlap in corrupt images.
164 memmove(buffer, SkTAddOffset<uint8_t>(buffer, fCurrRLEByte), remainingBytes);
165
166 // Adjust the buffer ptr to the start of the unfilled data.
167 buffer += remainingBytes;
168
169 // Try to read additional bytes from the stream. There are fCurrRLEByte
170 // bytes of additional space remaining in the buffer, assuming that we
171 // have already copied remainingBytes to the start of the buffer.
172 size_t additionalBytes = this->stream()->read(buffer, fCurrRLEByte);
173
174 // Update counters and return the number of bytes we currently have
175 // available. We are at the start of the buffer again.
176 fCurrRLEByte = 0;
177 fBytesBuffered = remainingBytes + additionalBytes;
178 return fBytesBuffered;
179}
180
181/*
182 * Set an RLE pixel using the color table
183 */
184void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes,
185 const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
186 uint8_t index) {
187 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) {
188 // Set the row
189 uint32_t row = this->getDstRow(y, dstInfo.height());
190
191 // Set the pixel based on destination color type
192 const int dstX = get_dst_coord(x, fSampleX);
193 switch (dstInfo.colorType()) {
196 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes);
197 dstRow[dstX] = fColorTable->operator[](index);
198 break;
199 }
201 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRowBytes);
202 dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index));
203 break;
204 }
205 default:
206 // This case should not be reached. We should catch an invalid
207 // color type when we check that the conversion is possible.
208 SkASSERT(false);
209 break;
210 }
211 }
212}
213
214/*
215 * Set an RLE pixel from R, G, B values
216 */
217void SkBmpRLECodec::setRGBPixel(void* dst, size_t dstRowBytes,
218 const SkImageInfo& dstInfo, uint32_t x,
219 uint32_t y, uint8_t red, uint8_t green,
220 uint8_t blue) {
221 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) {
222 // Set the row
223 uint32_t row = this->getDstRow(y, dstInfo.height());
224
225 // Set the pixel based on destination color type
226 const int dstX = get_dst_coord(x, fSampleX);
227 switch (dstInfo.colorType()) {
229 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes);
230 dstRow[dstX] = SkPackARGB_as_RGBA(0xFF, red, green, blue);
231 break;
232 }
234 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes);
235 dstRow[dstX] = SkPackARGB_as_BGRA(0xFF, red, green, blue);
236 break;
237 }
239 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRowBytes);
240 dstRow[dstX] = SkPack888ToRGB16(red, green, blue);
241 break;
242 }
243 default:
244 // This case should not be reached. We should catch an invalid
245 // color type when we check that the conversion is possible.
246 SkASSERT(false);
247 break;
248 }
249 }
250}
251
253 const SkCodec::Options& options) {
254 // FIXME: Support subsets for scanline decodes.
255 if (options.fSubset) {
256 // Subsets are not supported.
257 return kUnimplemented;
258 }
259
260 // Reset fSampleX. If it needs to be a value other than 1, it will get modified by
261 // the sampler.
262 fSampleX = 1;
263 fLinesToSkip = 0;
264
265 SkColorType colorTableColorType = dstInfo.colorType();
266 if (this->colorXform()) {
267 // Just set a known colorType for the colorTable. No need to actually transform
268 // the colors in the colorTable.
269 colorTableColorType = kBGRA_8888_SkColorType;
270 }
271
272 // Create the color table if necessary and prepare the stream for decode
273 // Note that if it is non-NULL, inputColorCount will be modified
274 if (!this->createColorTable(colorTableColorType)) {
275 SkCodecPrintf("Error: could not create color table.\n");
277 }
278
279 // Initialize a buffer for encoded RLE data
280 if (!this->initializeStreamBuffer()) {
281 SkCodecPrintf("Error: cannot initialize stream buffer.\n");
283 }
284
285 return SkCodec::kSuccess;
286}
287
288/*
289 * Performs the bitmap decoding for RLE input format
290 * RLE decoding is performed all at once, rather than a one row at a time
291 */
292int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowBytes,
293 const Options& opts) {
294 int height = info.height();
295
296 // Account for sampling.
297 SkImageInfo dstInfo = info.makeWH(this->fillWidth(), height);
298
299 // Set the background as transparent. Then, if the RLE code skips pixels,
300 // the skipped pixels will be transparent.
301 if (dst) {
302 SkSampler::Fill(dstInfo, dst, dstRowBytes, opts.fZeroInitialized);
303 }
304
305 // Adjust the height and the dst if the previous call to decodeRows() left us
306 // with lines that need to be skipped.
307 if (height > fLinesToSkip) {
308 height -= fLinesToSkip;
309 if (dst) {
310 dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes);
311 }
312 fLinesToSkip = 0;
313
315 } else {
316 fLinesToSkip -= height;
317 return height;
318 }
319
320 void* decodeDst = dst;
321 size_t decodeRowBytes = dstRowBytes;
322 SkImageInfo decodeInfo = dstInfo;
323 if (decodeDst) {
324 if (this->colorXform()) {
325 decodeInfo = decodeInfo.makeColorType(kXformSrcColorType);
327 int count = height * dstInfo.width();
328 this->resetXformBuffer(count);
329 sk_bzero(this->xformBuffer(), count * sizeof(uint32_t));
330 decodeDst = this->xformBuffer();
331 decodeRowBytes = dstInfo.width() * sizeof(uint32_t);
332 }
333 }
334 }
335
336 int decodedHeight = this->decodeRLE(decodeInfo, decodeDst, decodeRowBytes);
337 if (this->colorXform() && decodeDst) {
338 for (int y = 0; y < decodedHeight; y++) {
339 this->applyColorXform(dst, decodeDst, dstInfo.width());
340 decodeDst = SkTAddOffset<void>(decodeDst, decodeRowBytes);
341 dst = SkTAddOffset<void>(dst, dstRowBytes);
342 }
343 }
344
345 return decodedHeight;
346}
347
348int SkBmpRLECodec::decodeRLE(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes) {
349 // Use the original width to count the number of pixels in each row.
350 const int width = this->dimensions().width();
351
352 // This tells us the number of rows that we are meant to decode.
353 const int height = dstInfo.height();
354
355 // Set RLE flags
356 constexpr uint8_t RLE_ESCAPE = 0;
357 constexpr uint8_t RLE_EOL = 0;
358 constexpr uint8_t RLE_EOF = 1;
359 constexpr uint8_t RLE_DELTA = 2;
360
361 // Destination parameters
362 int x = 0;
363 int y = 0;
364
365 while (true) {
366 // If we have reached a row that is beyond the requested height, we have
367 // succeeded.
368 if (y >= height) {
369 // It would be better to check for the EOF marker before indicating
370 // success, but we may be performing a scanline decode, which
371 // would require us to stop before decoding the full height.
372 return height;
373 }
374
375 // Every entry takes at least two bytes
376 if ((int) fBytesBuffered - fCurrRLEByte < 2) {
377 if (this->checkForMoreData() < 2) {
378 return y;
379 }
380 }
381
382 // Read the next two bytes. These bytes have different meanings
383 // depending on their values. In the first interpretation, the first
384 // byte is an escape flag and the second byte indicates what special
385 // task to perform.
386 const uint8_t flag = fStreamBuffer[fCurrRLEByte++];
387 const uint8_t task = fStreamBuffer[fCurrRLEByte++];
388
389 // Perform decoding
390 if (RLE_ESCAPE == flag) {
391 switch (task) {
392 case RLE_EOL:
393 x = 0;
394 y++;
395 break;
396 case RLE_EOF:
397 return height;
398 case RLE_DELTA: {
399 // Two bytes are needed to specify delta
400 if ((int) fBytesBuffered - fCurrRLEByte < 2) {
401 if (this->checkForMoreData() < 2) {
402 return y;
403 }
404 }
405 // Modify x and y
406 const uint8_t dx = fStreamBuffer[fCurrRLEByte++];
407 const uint8_t dy = fStreamBuffer[fCurrRLEByte++];
408 x += dx;
409 y += dy;
410 if (x > width) {
411 SkCodecPrintf("Warning: invalid RLE input.\n");
412 return y - dy;
413 } else if (y > height) {
414 fLinesToSkip = y - height;
415 return height;
416 }
417 break;
418 }
419 default: {
420 // If task does not match any of the above signals, it
421 // indicates that we have a sequence of non-RLE pixels.
422 // Furthermore, the value of task is equal to the number
423 // of pixels to interpret.
424 uint8_t numPixels = task;
425 const size_t rowBytes = compute_row_bytes(numPixels,
426 this->bitsPerPixel());
427 if (x + numPixels > width) {
428 SkCodecPrintf("Warning: invalid RLE input.\n");
429 }
430
431 // Abort if there are not enough bytes
432 // remaining in the stream to set numPixels.
433
434 // At most, alignedRowBytes can be 255 (max uint8_t) *
435 // 3 (max bytes per pixel) + 1 (aligned) = 766. If
436 // fStreamBuffer was smaller than this,
437 // checkForMoreData would never succeed for some bmps.
438 static_assert(255 * 3 + 1 < kBufferSize,
439 "kBufferSize needs to be larger!");
440 const size_t alignedRowBytes = SkAlign2(rowBytes);
441 if ((int) fBytesBuffered - fCurrRLEByte < alignedRowBytes) {
442 SkASSERT(alignedRowBytes < kBufferSize);
443 if (this->checkForMoreData() < alignedRowBytes) {
444 return y;
445 }
446 }
447 // Set numPixels number of pixels
448 while ((numPixels > 0) && (x < width)) {
449 switch(this->bitsPerPixel()) {
450 case 4: {
451 SkASSERT(fCurrRLEByte < fBytesBuffered);
452 uint8_t val = fStreamBuffer[fCurrRLEByte++];
453 setPixel(dst, dstRowBytes, dstInfo, x++,
454 y, val >> 4);
455 numPixels--;
456 if (numPixels != 0) {
457 setPixel(dst, dstRowBytes, dstInfo,
458 x++, y, val & 0xF);
459 numPixels--;
460 }
461 break;
462 }
463 case 8:
464 SkASSERT(fCurrRLEByte < fBytesBuffered);
465 setPixel(dst, dstRowBytes, dstInfo, x++,
466 y, fStreamBuffer[fCurrRLEByte++]);
467 numPixels--;
468 break;
469 case 24: {
470 SkASSERT(fCurrRLEByte + 2 < fBytesBuffered);
471 uint8_t blue = fStreamBuffer[fCurrRLEByte++];
472 uint8_t green = fStreamBuffer[fCurrRLEByte++];
473 uint8_t red = fStreamBuffer[fCurrRLEByte++];
474 setRGBPixel(dst, dstRowBytes, dstInfo,
475 x++, y, red, green, blue);
476 numPixels--;
477 break;
478 }
479 default:
480 SkASSERT(false);
481 return y;
482 }
483 }
484 // Skip a byte if necessary to maintain alignment
485 if (!SkIsAlign2(rowBytes)) {
486 fCurrRLEByte++;
487 }
488 break;
489 }
490 }
491 } else {
492 // If the first byte read is not a flag, it indicates the number of
493 // pixels to set in RLE mode.
494 const uint8_t numPixels = flag;
495 const int endX = std::min<int>(x + numPixels, width);
496
497 if (24 == this->bitsPerPixel()) {
498 // In RLE24, the second byte read is part of the pixel color.
499 // There are two more required bytes to finish encoding the
500 // color.
501 if ((int) fBytesBuffered - fCurrRLEByte < 2) {
502 if (this->checkForMoreData() < 2) {
503 return y;
504 }
505 }
506
507 // Fill the pixels up to endX with the specified color
508 uint8_t blue = task;
509 uint8_t green = fStreamBuffer[fCurrRLEByte++];
510 uint8_t red = fStreamBuffer[fCurrRLEByte++];
511 while (x < endX) {
512 setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, green, blue);
513 }
514 } else {
515 // In RLE8 or RLE4, the second byte read gives the index in the
516 // color table to look up the pixel color.
517 // RLE8 has one color index that gets repeated
518 // RLE4 has two color indexes in the upper and lower 4 bits of
519 // the bytes, which are alternated
520 uint8_t indices[2] = { task, task };
521 if (4 == this->bitsPerPixel()) {
522 indices[0] >>= 4;
523 indices[1] &= 0xf;
524 }
525
526 // Set the indicated number of pixels
527 for (int which = 0; x < endX; x++) {
528 setPixel(dst, dstRowBytes, dstInfo, x, y, indices[which]);
529 which = !which;
530 }
531 }
532 }
533 }
534}
535
536bool SkBmpRLECodec::skipRows(int count) {
537 const SkImageInfo rowInfo = SkImageInfo::Make(this->dimensions().width(), count,
538 kN32_SkColorType, kUnpremul_SkAlphaType);
539 return count == this->decodeRows(rowInfo, nullptr, 0, this->options());
540}
541
542// FIXME: Make SkBmpRLECodec have no knowledge of sampling.
543// Or it should do all sampling natively.
544// It currently is a hybrid that needs to know what SkScaledCodec is doing.
546public:
548 : fCodec(codec)
549 {
550 SkASSERT(fCodec);
551 }
552
553 int fillWidth() const override {
554 return fCodec->fillWidth();
555 }
556
557private:
558 int onSetSampleX(int sampleX) override {
559 return fCodec->setSampleX(sampleX);
560 }
561
562 // Unowned pointer. fCodec will delete this class in its destructor.
563 SkBmpRLECodec* fCodec;
564};
565
566SkSampler* SkBmpRLECodec::getSampler(bool createIfNecessary) {
567 if (!fSampler && createIfNecessary) {
568 fSampler = std::make_unique<SkBmpRLESampler>(this);
569 }
570
571 return fSampler.get();
572}
573
575 fSampleX = sampleX;
576 return this->fillWidth();
577}
578
580 return get_scaled_dimension(this->dimensions().width(), fSampleX);
581}
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
sk_bzero(glyphs, sizeof(glyphs))
int count
Definition: FontMgrTest.cpp:50
kUnpremul_SkAlphaType
static constexpr bool SkIsAlign2(T x)
Definition: SkAlign.h:19
static constexpr T SkAlign2(T x)
Definition: SkAlign.h:15
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool is_coord_necessary(int srcCoord, int sampleFactor, int scaledDim)
Definition: SkCodecPriv.h:77
static uint8_t get_byte(const uint8_t *buffer, uint32_t i)
Definition: SkCodecPriv.h:146
uint32_t(* PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkCodecPriv.h:239
static PackColorProc choose_pack_color_proc(bool isPremul, SkColorType colorType)
Definition: SkCodecPriv.h:241
static size_t compute_row_bytes(int width, uint32_t bitsPerPixel)
Definition: SkCodecPriv.h:130
static int get_dst_coord(int srcCoord, int sampleFactor)
Definition: SkCodecPriv.h:67
static int get_scaled_dimension(int srcDimension, int sampleSize)
Definition: SkCodecPriv.h:44
#define SkCodecPrintf(...)
Definition: SkCodecPriv.h:23
static uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColorData.h:65
static U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b)
Definition: SkColorData.h:324
static U16CPU SkPixel32ToPixel16(SkPMColor c)
Definition: SkColorData.h:317
static uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColorData.h:74
static SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColorPriv.h:120
SkColorType
Definition: SkColorType.h:19
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition: SkColorType.h:38
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition: SkColorType.h:22
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
uint32_t SkPMColor
Definition: SkColor.h:205
static bool read(SkStream *stream, void *buffer, size_t amount)
static bool skip(SkStream *stream, size_t amount)
void resetXformBuffer(int count)
Definition: SkBmpCodec.h:105
int32_t getDstRow(int32_t y, int32_t height) const
Definition: SkBmpCodec.cpp:634
SkCodec::Result prepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)
Definition: SkBmpCodec.cpp:642
uint32_t * xformBuffer() const
Definition: SkBmpCodec.h:104
static constexpr SkColorType kXformSrcColorType
Definition: SkBmpCodec.h:111
uint16_t bitsPerPixel() const
Definition: SkBmpCodec.h:87
int fillWidth() const
Result onGetPixels(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &, int *) override
SkCodec::Result onPrepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options) override
int setSampleX(int)
SkBmpRLECodec(SkEncodedInfo &&info, std::unique_ptr< SkStream >, uint16_t bitsPerPixel, uint32_t numColors, uint32_t bytesPerColor, uint32_t offset, SkCodec::SkScanlineOrder rowOrder)
SkBmpRLESampler(SkBmpRLECodec *codec)
int fillWidth() const override
SkISize dimensions() const
Definition: SkCodec.h:230
const SkImageInfo & dstInfo() const
Definition: SkCodec.h:878
SkStream * stream()
Definition: SkCodec.h:865
void applyColorXform(void *dst, const void *src, int count) const
Definition: SkCodec.cpp:853
SkScanlineOrder
Definition: SkCodec.h:575
Result
Definition: SkCodec.h:76
@ kIncompleteInput
Definition: SkCodec.h:84
@ kInvalidInput
Definition: SkCodec.h:109
@ kUnimplemented
Definition: SkCodec.h:123
@ kSuccess
Definition: SkCodec.h:80
bool colorXform() const
Definition: SkCodec.h:906
const Options & options() const
Definition: SkCodec.h:880
static void Fill(const SkImageInfo &info, void *dst, size_t rowBytes, SkCodec::ZeroInitialized zeroInit)
Definition: SkSampler.cpp:20
virtual size_t read(void *buffer, size_t size)=0
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
FlutterSemanticsFlag flag
GAsyncResult * result
static float min(float r, float g, float b)
Definition: hsl.cpp:48
double y
double x
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
dst
Definition: cp.py:12
Definition: ref_ptr.h:256
int32_t height
int32_t width
SeparatedVector2 offset
const SkIRect * fSubset
Definition: SkCodec.h:347
constexpr int32_t width() const
Definition: SkSize.h:36
SkImageInfo makeWH(int newWidth, int newHeight) const
Definition: SkImageInfo.h:444
int width() const
Definition: SkImageInfo.h:365
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkColorType colorType() const
Definition: SkImageInfo.h:373
int height() const
Definition: SkImageInfo.h:371
SkImageInfo makeColorType(SkColorType newColorType) const
Definition: SkImageInfo.h:475