Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.
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
285 return this->readArray(value, size, sizeof(uint8_t));
286}
287
289 return this->readArray(colors, size, sizeof(SkColor));
290}
291
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
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) {
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 {
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
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
Definition: FontMgrTest.cpp:50
static const int points[]
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()
Definition: SkAutoMalloc.h:64
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 &)
Definition: SkFlattenable.h:41
virtual Type getFlattenableType() const =0
static Factory NameToFactory(const char name[])
sk_sp< SkImage > makeRasterImage(GrDirectContext *, CachingHint cachingHint=kDisallow_CachingHint) const
Definition: SkImage.cpp:267
const SkImageInfo & imageInfo() const
Definition: SkImage.h:279
SkISize dimensions() const
Definition: SkImage.h:297
bool readPixels(GrDirectContext *context, const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY, CachingHint cachingHint=kAllow_CachingHint) const
Definition: SkImage.cpp:42
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)
Definition: SkMatrixPriv.h:34
SkMatrix & reset()
Definition: SkMatrix.cpp:49
Definition: SkPath.h:59
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)
Definition: SkReadBuffer.h:191
bool readIntArray(int32_t *values, size_t size)
uint32_t readUInt()
bool isValid() const
Definition: SkReadBuffer.h:208
const void * skip(size_t size)
sk_sp< SkData > readByteArrayAsData()
void readIRect(SkIRect *rect)
void setAllowSkSL(bool allow)
Definition: SkReadBuffer.h:185
int32_t read32()
void setDeserialProcs(const SkDeserialProcs &procs)
SkSamplingOptions readSampling()
size_t size() const
Definition: SkReadBuffer.h:77
void read(SkM44 *)
bool readPointArray(SkPoint *points, size_t size)
size_t available() const
Definition: SkReadBuffer.h:82
SkRect readRect()
int32_t readInt()
sk_sp< SkTypeface > readTypeface()
void readString(SkString *string)
bool readColorArray(SkColor *colors, size_t size)
size_t offset() const
Definition: SkReadBuffer.h:78
bool readPad32(void *buffer, size_t bytes)
int32_t checkInt(int min, int max)
sk_sp< T > readFlattenable()
Definition: SkReadBuffer.h:133
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)
Definition: SkReadBuffer.h:99
bool isVersionLT(SkPicturePriv::Version targetVersion) const
Definition: SkReadBuffer.h:64
SkPoint readPoint()
Definition: SkReadBuffer.h:115
void unref() const
Definition: SkRefCnt.h:72
size_t readFromMemory(const void *buffer, size_t length)
Definition: SkRegion.cpp:1276
bool setEmpty()
Definition: SkRegion.cpp:185
static size_t Mul(size_t x, size_t y)
Definition: SkSafeMath.cpp:16
T * release()
Definition: SkRefCnt.h:324
int count() const
Definition: SkTHash.h:471
V * find(const K &key) const
Definition: SkTHash.h:494
V * set(K key, V val)
Definition: SkTHash.h:487
DlColor color
float SkScalar
Definition: extension.cpp:12
FlutterSemanticsFlag flags
uint8_t value
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)
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
sk_sp< const SkImage > image
Definition: SkRecords.h:269
ClipOpAndAA opAA SkRegion region
Definition: SkRecords.h:238
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
PODArray< SkColor > colors
Definition: SkRecords.h:276
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
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SkSamplingOptions(SkFilterMode::kLinear))
int32_t height
int32_t width
SkDeserialTypefaceProc fTypefaceProc
SkDeserialImageProc fImageProc
SkDeserialImageFromDataProc fImageDataProc
Definition: SkRect.h:32
static SkImageInfo MakeN32Premul(int width, int height)
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
void setEmpty()
Definition: SkRect.h:842
static constexpr SkSamplingOptions Aniso(int maxAniso)
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63