Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkReadBuffer.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 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
11#include "include/core/SkData.h"
15#include "include/core/SkM44.h"
17#include "include/core/SkPath.h"
22#include "include/core/SkSize.h"
27#include "src/base/SkMathPriv.h"
28#include "src/base/SkSafeMath.h"
32
33#include <memory>
34#include <optional>
35#include <utility>
36
37namespace {
38 // This generator intentionally should always fail on all attempts to get its pixels,
39 // simulating a bad or empty codec stream.
40 class EmptyImageGenerator final : public SkImageGenerator {
41 public:
42 EmptyImageGenerator(const SkImageInfo& info) : SkImageGenerator(info) { }
43
44 };
45
46 static sk_sp<SkImage> MakeEmptyImage(int width, int height) {
48 std::make_unique<EmptyImageGenerator>(SkImageInfo::MakeN32Premul(width, height)));
49 }
50
51} // anonymous namespace
52
53void SkReadBuffer::setMemory(const void* data, size_t size) {
54 this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
55 if (!fError) {
56 fBase = fCurr = (const char*)data;
57 fStop = fBase + size;
58 }
59}
60
61void SkReadBuffer::setInvalid() {
62 if (!fError) {
63 // When an error is found, send the read cursor to the end of the stream
64 fCurr = fStop;
65 fError = true;
66 }
67}
68
69const void* SkReadBuffer::skip(size_t size) {
70 size_t inc = SkAlign4(size);
71 this->validate(inc >= size);
72 const void* addr = fCurr;
73 this->validate(IsPtrAlign4(addr) && this->isAvailable(inc));
74 if (fError) {
75 return nullptr;
76 }
77
78 fCurr += inc;
79 return addr;
80}
81
82const void* SkReadBuffer::skip(size_t count, size_t size) {
83 return this->skip(SkSafeMath::Mul(count, size));
84}
85
87 fProcs = procs;
88 this->setAllowSkSL(procs.fAllowSkSL);
89}
90
92 uint32_t value = this->readUInt();
93 // Boolean value should be either 0 or 1
94 this->validate(!(value & ~1));
95 return value != 0;
96}
97
99 return this->readUInt();
100}
101
103 const size_t inc = sizeof(int32_t);
104 if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
105 return 0;
106 }
107 int32_t value = *((const int32_t*)fCurr);
108 fCurr += inc;
109 return value;
110}
111
113 const size_t inc = sizeof(SkScalar);
114 if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
115 return 0;
116 }
117 SkScalar value = *((const SkScalar*)fCurr);
118 fCurr += inc;
119 return value;
120}
121
123 return this->readInt();
124}
125
127 return this->readInt();
128}
129
131 if (this->available() <= 0) {
132 fError = true;
133 return 0;
134 }
135 return *((const uint8_t*)fCurr);
136}
137
138bool SkReadBuffer::readPad32(void* buffer, size_t bytes) {
139 if (const void* src = this->skip(bytes)) {
140 // buffer might be null if bytes is zero (see SkAutoMalloc), hence we call
141 // the careful version of memcpy.
142 sk_careful_memcpy(buffer, src, bytes);
143 return true;
144 }
145 return false;
146}
147
148const char* SkReadBuffer::readString(size_t* len) {
149 *len = this->readUInt();
150
151 // The string is len characters and a terminating \0.
152 const char* c_str = this->skipT<char>(*len+1);
153
154 if (this->validate(c_str && c_str[*len] == '\0')) {
155 return c_str;
156 }
157 return nullptr;
158}
159
161 size_t len;
162 if (const char* c_str = this->readString(&len)) {
163 string->set(c_str, len);
164 return;
165 }
166 string->reset();
167}
168
170 if (!this->readPad32(color, sizeof(SkColor4f))) {
171 *color = {0, 0, 0, 0};
172 }
173}
174
176 point->fX = this->readScalar();
177 point->fY = this->readScalar();
178}
179
181 this->readPad32(point, sizeof(SkPoint3));
182}
183
185 if (this->isValid()) {
186 if (const float* m = (const float*)this->skip(sizeof(float) * 16)) {
187 *matrix = SkM44::ColMajor(m);
188 }
189 }
190 if (!this->isValid()) {
191 *matrix = SkM44();
192 }
193}
194
196 size_t size = 0;
197 if (this->isValid()) {
198 size = SkMatrixPriv::ReadFromMemory(matrix, fCurr, this->available());
199 (void)this->validate((SkAlign4(size) == size) && (0 != size));
200 }
201 if (!this->isValid()) {
202 matrix->reset();
203 }
204 (void)this->skip(size);
205}
206
208 if (!this->readPad32(rect, sizeof(SkIRect))) {
209 rect->setEmpty();
210 }
211}
212
214 if (!this->readPad32(rect, sizeof(SkRect))) {
215 rect->setEmpty();
216 }
217}
218
220 SkRect r;
221 if (!this->readPad32(&r, sizeof(SkRect))) {
222 r.setEmpty();
223 }
224 return r;
225}
226
229 int maxAniso = this->readInt();
230 if (maxAniso != 0) {
231 return SkSamplingOptions::Aniso(maxAniso);
232 }
233 }
234 if (this->readBool()) {
235 float B = this->readScalar();
236 float C = this->readScalar();
237 return SkSamplingOptions({B, C});
238 } else {
241 return SkSamplingOptions(filter, mipmap);
242 }
243}
244
246 size_t size = 0;
247 if (!fError) {
248 size = rrect->readFromMemory(fCurr, this->available());
249 if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
250 rrect->setEmpty();
251 }
252 }
253 (void)this->skip(size);
254}
255
257 size_t size = 0;
258 if (!fError) {
259 size = region->readFromMemory(fCurr, this->available());
260 if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
261 region->setEmpty();
262 }
263 }
264 (void)this->skip(size);
265}
266
268 size_t size = 0;
269 if (!fError) {
270 size = path->readFromMemory(fCurr, this->available());
271 if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
272 path->reset();
273 }
274 }
275 (void)this->skip(size);
276}
277
278bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
279 const uint32_t count = this->readUInt();
280 return this->validate(size == count) &&
281 this->readPad32(value, SkSafeMath::Mul(size, elementSize));
282}
283
284bool SkReadBuffer::readByteArray(void* value, size_t size) {
285 return this->readArray(value, size, sizeof(uint8_t));
286}
287
288bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
289 return this->readArray(colors, size, sizeof(SkColor));
290}
291
292bool SkReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
293 return this->readArray(colors, size, sizeof(SkColor4f));
294}
295
296bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
297 return this->readArray(values, size, sizeof(int32_t));
298}
299
301 return this->readArray(points, size, sizeof(SkPoint));
302}
303
304bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
305 return this->readArray(values, size, sizeof(SkScalar));
306}
307
308const void* SkReadBuffer::skipByteArray(size_t* size) {
309 const uint32_t count = this->readUInt();
310 const void* buf = this->skip(count);
311 if (size) {
312 *size = this->isValid() ? count : 0;
313 }
314 return buf;
315}
316
318 size_t numBytes = this->getArrayCount();
319 if (!this->validate(this->isAvailable(numBytes))) {
320 return nullptr;
321 }
322
323 SkAutoMalloc buffer(numBytes);
324 if (!this->readByteArray(buffer.get(), numBytes)) {
325 return nullptr;
326 }
327 return SkData::MakeFromMalloc(buffer.release(), numBytes);
328}
329
331 const size_t inc = sizeof(uint32_t);
332 if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
333 return 0;
334 }
335 return *((const uint32_t*)fCurr);
336}
337
339 std::optional<SkAlphaType> alphaType) {
341 if (dProcs.fImageDataProc) {
342 image = dProcs.fImageDataProc(data, alphaType, dProcs.fImageCtx);
343 } else if (dProcs.fImageProc) {
344#if !defined(SK_LEGACY_DESERIAL_IMAGE_PROC)
345 image = dProcs.fImageProc(data->data(), data->size(), dProcs.fImageCtx);
346#else
347 image = dProcs.fImageProc(data->data(), data->size(), alphaType, dProcs.fImageCtx);
348#endif
349 }
350 if (image) {
351 return image;
352 }
353#if !defined(SK_DISABLE_LEGACY_IMAGE_READBUFFER)
354 // The default implementation will encode to PNG unless the input SkImages came from
355 // a codec that was built-in (e.g. JPEG/WEBP). Thus, we should be sure to try all
356 // available codecs when reading images out of an SKP.
357 return SkImages::DeferredFromEncodedData(std::move(data), alphaType);
358#else
359 SkDEBUGFAIL("Need to set image proc in SkDeserialProcs");
360 return nullptr;
361#endif
362}
363
365 SkDeserialProcs dProcs, std::optional<SkAlphaType> alphaType) {
366 SkMipmapBuilder builder(img->imageInfo());
367
368 SkReadBuffer buffer(data->data(), data->size());
369 int count = buffer.read32();
370 if (builder.countLevels() != count) {
371 return img;
372 }
373 for (int i = 0; i < count; ++i) {
374 size_t size = buffer.read32();
375 const void* ptr = buffer.skip(size);
376 if (!ptr) {
377 return img;
378 }
379 // This use of SkData::MakeWithoutCopy is safe because the image goes
380 // out of scope after we read the pixels from it, so we are sure the
381 // data (from buffer) outlives the image.
383 alphaType);
384 if (!mip) {
385 return img;
386 }
387
388 SkPixmap pm = builder.level(i);
389 if (mip->dimensions() != pm.dimensions()) {
390 return img;
391 }
392 if (!mip->readPixels(nullptr, pm, 0, 0)) {
393 return img;
394 }
395 }
396 if (!buffer.isValid()) {
397 return img;
398 }
399 sk_sp<SkImage> raster = img->makeRasterImage();
400 if (!raster) {
401 return img;
402 }
403 sk_sp<SkImage> rasterWithMips = builder.attachTo(raster);
404 SkASSERT(rasterWithMips); // attachTo should never return null
405 return rasterWithMips;
406}
407
408
409// If we see a corrupt stream, we return null (fail). If we just fail trying to decode
410// the image, we don't fail, but return a 1x1 empty image.
412 uint32_t flags = this->read32();
413
414 std::optional<SkAlphaType> alphaType = std::nullopt;
416 alphaType = kUnpremul_SkAlphaType;
417 }
419 {
420 sk_sp<SkData> data = this->readByteArrayAsData();
421 if (!data) {
422 this->validate(false);
423 return nullptr;
424 }
425 image = deserialize_image(data, fProcs, alphaType);
426 }
427
428 // This flag is not written by new SKPs anymore.
430 SkIRect subset;
431 this->readIRect(&subset);
432 if (image) {
433 image = image->makeSubset(nullptr, subset);
434 }
435 }
436
438 sk_sp<SkData> data = this->readByteArrayAsData();
439 if (!data) {
440 this->validate(false);
441 return nullptr;
442 }
443 if (image) {
444 image = add_mipmaps(image, std::move(data), fProcs, alphaType);
445 }
446 }
447 return image ? image : MakeEmptyImage(1, 1);
448}
449
451 // Read 32 bits (signed)
452 // 0 -- return null (empty font)
453 // >0 -- index
454 // <0 -- custom (serial procs) : negative size in bytes
455
456 int32_t index = this->read32();
457 if (index == 0) {
458 return nullptr;
459 } else if (index > 0) {
460 if (!this->validate(index <= fTFCount)) {
461 return nullptr;
462 }
463 return fTFArray[index - 1];
464 } else { // custom
465 size_t size = sk_negate_to_size_t(index);
466 const void* data = this->skip(size);
467 if (!this->validate(data != nullptr && fProcs.fTypefaceProc)) {
468 return nullptr;
469 }
470 return fProcs.fTypefaceProc(data, size, fProcs.fTypefaceCtx);
471 }
472}
473
475 SkFlattenable::Factory factory = nullptr;
476
477 if (fFactoryCount > 0) {
478 int32_t index = this->read32();
479 if (0 == index || !this->isValid()) {
480 return nullptr; // writer failed to give us the flattenable
481 }
482 if (index < 0) {
483 this->validate(false);
484 return nullptr;
485 }
486 index -= 1; // we stored the index-base-1
487 if ((unsigned)index >= (unsigned)fFactoryCount) {
488 this->validate(false);
489 return nullptr;
490 }
491 factory = fFactoryArray[index];
492 } else {
493 if (this->peekByte() != 0) {
494 // If the first byte is non-zero, the flattenable is specified by a string.
495 size_t ignored_length;
496 if (const char* name = this->readString(&ignored_length)) {
498 fFlattenableDict.set(fFlattenableDict.count() + 1, factory);
499 }
500 } else {
501 // Read the index. We are guaranteed that the first byte
502 // is zeroed, so we must shift down a byte.
503 uint32_t index = this->readUInt() >> 8;
504 if (index == 0) {
505 return nullptr; // writer failed to give us the flattenable
506 }
507
508 if (SkFlattenable::Factory* found = fFlattenableDict.find(index)) {
509 factory = *found;
510 }
511 }
512
513 if (!this->validate(factory != nullptr)) {
514 return nullptr;
515 }
516 }
517
518 // if we get here, factory may still be null, but if that is the case, the
519 // failure was ours, not the writer.
521 uint32_t sizeRecorded = this->read32();
522 if (factory) {
523 size_t offset = this->offset();
524 obj = (*factory)(*this);
525 // check that we read the amount we expected
526 size_t sizeRead = this->offset() - offset;
527 if (sizeRecorded != sizeRead) {
528 this->validate(false);
529 return nullptr;
530 }
531 } else {
532 // we must skip the remaining data
533 this->skip(sizeRecorded);
534 }
535 if (!this->isValid()) {
536 return nullptr;
537 }
538 return obj.release();
539}
540
542 SkFlattenable* obj = this->readRawFlattenable();
543 if (obj && obj->getFlattenableType() != ft) {
544 this->validate(false);
545 obj->unref();
546 return nullptr;
547 }
548 return obj;
549}
550
551///////////////////////////////////////////////////////////////////////////////////////////////////
552
553int32_t SkReadBuffer::checkInt(int32_t min, int32_t max) {
554 SkASSERT(min <= max);
555 int32_t value = this->read32();
556 if (value < min || value > max) {
557 this->validate(false);
558 value = min;
559 }
560 return value;
561}
562
564 return this->checkRange<SkLegacyFQ>(kNone_SkLegacyFQ, kLast_SkLegacyFQ);
565}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
static const int points[]
SkColor4f color
kUnpremul_SkAlphaType
static constexpr T SkAlign4(T x)
Definition SkAlign.h:16
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
uint32_t SkColor
Definition SkColor.h:37
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
Definition SkMalloc.h:125
static size_t sk_negate_to_size_t(int32_t value)
Definition SkMathPriv.h:76
static sk_sp< SkImage > add_mipmaps(sk_sp< SkImage > img, sk_sp< SkData > data, SkDeserialProcs dProcs, std::optional< SkAlphaType > alphaType)
static sk_sp< SkImage > deserialize_image(sk_sp< SkData > data, SkDeserialProcs dProcs, std::optional< SkAlphaType > alphaType)
SkFilterMode
SkMipmapMode
SkLegacyFQ
@ kLast_SkLegacyFQ
@ kNone_SkLegacyFQ
nearest-neighbor; fastest but lowest quality
@ kUnpremul
@ kHasSubsetRect
@ kHasMipmap
void * get()
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition SkData.h:116
static sk_sp< SkData > MakeFromMalloc(const void *data, size_t length)
Definition SkData.cpp:107
sk_sp< SkFlattenable >(* Factory)(SkReadBuffer &)
virtual Type getFlattenableType() const =0
static Factory NameToFactory(const char name[])
virtual sk_sp< SkImage > makeSubset(GrDirectContext *direct, const SkIRect &subset) const =0
Definition SkM44.h:150
static SkM44 ColMajor(const SkScalar c[16])
Definition SkM44.h:218
static size_t ReadFromMemory(SkMatrix *matrix, const void *buffer, size_t length)
SkMatrix & reset()
Definition SkMatrix.cpp:49
SkISize dimensions() const
Definition SkPixmap.h:171
void setEmpty()
Definition SkRRect.h:118
size_t readFromMemory(const void *buffer, size_t length)
Definition SkRRect.cpp:610
bool readColor4fArray(SkColor4f *colors, size_t size)
void readColor4f(SkColor4f *color)
SkLegacyFQ checkFilterQuality()
SkFlattenable * readRawFlattenable()
const void * skipByteArray(size_t *size)
void readMatrix(SkMatrix *matrix)
void setMemory(const void *, size_t)
bool readByteArray(void *value, size_t size)
uint8_t peekByte()
bool validate(bool isValid)
bool readIntArray(int32_t *values, size_t size)
uint32_t readUInt()
bool isValid() const
const void * skip(size_t size)
sk_sp< SkData > readByteArrayAsData()
void readIRect(SkIRect *rect)
void setAllowSkSL(bool allow)
int32_t read32()
void setDeserialProcs(const SkDeserialProcs &procs)
SkSamplingOptions readSampling()
size_t size() const
void read(SkM44 *)
bool readPointArray(SkPoint *points, size_t size)
size_t available() const
SkRect readRect()
int32_t readInt()
sk_sp< SkTypeface > readTypeface()
void readString(SkString *string)
bool readColorArray(SkColor *colors, size_t size)
size_t offset() const
bool readPad32(void *buffer, size_t bytes)
int32_t checkInt(int min, int max)
sk_sp< T > readFlattenable()
bool readScalarArray(SkScalar *values, size_t size)
SkColor readColor()
void readPoint3(SkPoint3 *point)
sk_sp< SkImage > readImage()
void readRRect(SkRRect *rrect)
uint32_t getArrayCount()
SkScalar readScalar()
void readRegion(SkRegion *region)
void readPath(SkPath *path)
T read32LE(T max)
bool isVersionLT(SkPicturePriv::Version targetVersion) const
SkPoint readPoint()
void unref() const
Definition SkRefCnt.h:72
size_t readFromMemory(const void *buffer, size_t length)
bool setEmpty()
Definition SkRegion.cpp:185
static size_t Mul(size_t x, size_t y)
T * release()
Definition SkRefCnt.h:324
int count() const
Definition SkTHash.h:460
V * find(const K &key) const
Definition SkTHash.h:479
V * set(K key, V val)
Definition SkTHash.h:472
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
FlutterSemanticsFlag flags
static const uint8_t buffer[]
uint8_t value
const char * name
Definition fuchsia.cc:50
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48
#define B
SK_API sk_sp< SkImage > DeferredFromEncodedData(sk_sp< SkData > encoded, std::optional< SkAlphaType > alphaType=std::nullopt)
SK_API sk_sp< SkImage > DeferredFromGenerator(std::unique_ptr< SkImageGenerator > imageGenerator)
int32_t height
int32_t width
SkDeserialTypefaceProc fTypefaceProc
SkDeserialImageProc fImageProc
SkDeserialImageFromDataProc fImageDataProc
static SkImageInfo MakeN32Premul(int width, int height)
float fX
x-axis value
float fY
y-axis value
void setEmpty()
Definition SkRect.h:842
static constexpr SkSamplingOptions Aniso(int maxAniso)