| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkReadBuffer_DEFINED |
| #define SkReadBuffer_DEFINED |
| |
| #include "SkColorFilter.h" |
| #include "SkData.h" |
| #include "SkSerialProcs.h" |
| #include "SkDrawLooper.h" |
| #include "SkImageFilter.h" |
| #include "SkMaskFilterBase.h" |
| #include "SkPath.h" |
| #include "SkPathEffect.h" |
| #include "SkPicture.h" |
| #include "SkReadBuffer.h" |
| #include "SkReader32.h" |
| #include "SkRefCnt.h" |
| #include "SkShaderBase.h" |
| #include "SkTHash.h" |
| #include "SkWriteBuffer.h" |
| |
| class SkImage; |
| class SkInflator; |
| |
| #if defined(SK_DEBUG) && defined(SK_BUILD_FOR_MAC) |
| #define DEBUG_NON_DETERMINISTIC_ASSERT |
| #endif |
| |
| class SkReadBuffer { |
| public: |
| SkReadBuffer(); |
| SkReadBuffer(const void* data, size_t size); |
| virtual ~SkReadBuffer(); |
| |
| virtual SkReadBuffer* clone(const void* data, size_t size) const { |
| return new SkReadBuffer(data, size); |
| } |
| |
| enum Version { |
| /* |
| kFilterLevelIsEnum_Version = 23, |
| kGradientFlippedFlag_Version = 24, |
| kDashWritesPhaseIntervals_Version = 25, |
| kColorShaderNoBool_Version = 26, |
| kNoUnitMappers_Version = 27, |
| kNoMoreBitmapFlatten_Version = 28, |
| kSimplifyLocalMatrix_Version = 30, |
| kImageFilterUniqueID_Version = 31, |
| kRemoveAndroidPaintOpts_Version = 32, |
| kFlattenCreateProc_Version = 33, |
| kRemoveColorTableAlpha_Version = 36, |
| kDropShadowMode_Version = 37, |
| kPictureImageFilterResolution_Version = 38, |
| kPictureImageFilterLevel_Version = 39, |
| kImageFilterNoUniqueID_Version = 40, |
| kBitmapSourceFilterQuality_Version = 41, |
| kPictureShaderHasPictureBool_Version = 42, |
| kHasDrawImageOpCodes_Version = 43, |
| kAnnotationsMovedToCanvas_Version = 44, |
| kLightingShaderWritesInvNormRotation = 45, |
| kBlurMaskFilterWritesOccluder = 47, |
| kGradientShaderFloatColor_Version = 49, |
| kXfermodeToBlendMode_Version = 50, |
| kXfermodeToBlendMode2_Version = 51, |
| kTextBlobImplicitRunCount_Version = 52, |
| kComposeShaderCanLerp_Version = 54, |
| kNoModesInMergeImageFilter_Verison = 55, |
| */ |
| kTileModeInBlurImageFilter_Version = 56, |
| kTileInfoInSweepGradient_Version = 57, |
| k2PtConicalNoFlip_Version = 58, |
| kRemovePictureImageFilterLocalSpace = 59, |
| kRemoveHeaderFlags_Version = 60, |
| kTwoColorDrawShadow_Version = 61, |
| }; |
| |
| /** |
| * Returns true IFF the version is older than the specified version. |
| */ |
| bool isVersionLT(Version targetVersion) const { |
| SkASSERT(targetVersion > 0); |
| return fVersion > 0 && fVersion < targetVersion; |
| } |
| |
| uint32_t getVersion() const { return fVersion; } |
| |
| /** This may be called at most once; most clients of SkReadBuffer should not mess with it. */ |
| void setVersion(int version) { |
| SkASSERT(0 == fVersion || version == fVersion); |
| fVersion = version; |
| } |
| |
| size_t size() { return fReader.size(); } |
| size_t offset() { return fReader.offset(); } |
| bool eof() { return fReader.eof(); } |
| const void* skip(size_t size); |
| const void* skip(size_t count, size_t size); // does safe multiply |
| |
| template <typename T> const T* skipT() { |
| return static_cast<const T*>(this->skip(sizeof(T))); |
| } |
| template <typename T> const T* skipT(size_t count) { |
| return static_cast<const T*>(this->skip(count, sizeof(T))); |
| } |
| |
| // primitives |
| bool readBool(); |
| SkColor readColor(); |
| int32_t readInt(); |
| SkScalar readScalar(); |
| uint32_t readUInt(); |
| int32_t read32(); |
| |
| template <typename T> T read32LE(T max) { |
| uint32_t value = this->readUInt(); |
| if (!this->validate(value <= static_cast<uint32_t>(max))) { |
| value = 0; |
| } |
| return static_cast<T>(value); |
| } |
| |
| // peek |
| uint8_t peekByte(); |
| |
| // strings -- the caller is responsible for freeing the string contents |
| void readString(SkString* string); |
| |
| // common data structures |
| void readColor4f(SkColor4f* color); |
| void readPoint(SkPoint* point); |
| SkPoint readPoint() { SkPoint p; this->readPoint(&p); return p; } |
| void readPoint3(SkPoint3* point); |
| void readMatrix(SkMatrix* matrix); |
| void readIRect(SkIRect* rect); |
| void readRect(SkRect* rect); |
| void readRRect(SkRRect* rrect); |
| void readRegion(SkRegion* region); |
| |
| void readPath(SkPath* path); |
| virtual bool readPaint(SkPaint* paint) { return paint->unflatten(*this); } |
| |
| SkFlattenable* readFlattenable(SkFlattenable::Type); |
| template <typename T> sk_sp<T> readFlattenable() { |
| return sk_sp<T>((T*)this->readFlattenable(T::GetFlattenableType())); |
| } |
| sk_sp<SkColorFilter> readColorFilter() { return this->readFlattenable<SkColorFilter>(); } |
| sk_sp<SkDrawLooper> readDrawLooper() { return this->readFlattenable<SkDrawLooper>(); } |
| sk_sp<SkImageFilter> readImageFilter() { return this->readFlattenable<SkImageFilter>(); } |
| sk_sp<SkMaskFilter> readMaskFilter() { return this->readFlattenable<SkMaskFilterBase>(); } |
| sk_sp<SkPathEffect> readPathEffect() { return this->readFlattenable<SkPathEffect>(); } |
| sk_sp<SkShader> readShader() { return this->readFlattenable<SkShaderBase>(); } |
| |
| // Reads SkAlign4(bytes), but will only copy bytes into the buffer. |
| bool readPad32(void* buffer, size_t bytes); |
| |
| // binary data and arrays |
| bool readByteArray(void* value, size_t size); |
| bool readColorArray(SkColor* colors, size_t size); |
| bool readColor4fArray(SkColor4f* colors, size_t size); |
| bool readIntArray(int32_t* values, size_t size); |
| bool readPointArray(SkPoint* points, size_t size); |
| bool readScalarArray(SkScalar* values, size_t size); |
| |
| sk_sp<SkData> readByteArrayAsData() { |
| size_t len = this->getArrayCount(); |
| void* buffer = sk_malloc_throw(len); |
| if (!this->readByteArray(buffer, len)) { |
| sk_free(buffer); |
| return SkData::MakeEmpty(); |
| } |
| return SkData::MakeFromMalloc(buffer, len); |
| } |
| |
| // helpers to get info about arrays and binary data |
| uint32_t getArrayCount(); |
| |
| // If there is a real error (e.g. data is corrupted) this returns null. If the image cannot |
| // be created (e.g. it was not originally encoded) then this returns an image that doesn't |
| // draw. |
| sk_sp<SkImage> readImage(); |
| sk_sp<SkTypeface> readTypeface(); |
| |
| void setTypefaceArray(SkTypeface* array[], int count) { |
| fTFArray = array; |
| fTFCount = count; |
| } |
| |
| /** |
| * Call this with a pre-loaded array of Factories, in the same order as |
| * were created/written by the writer. SkPicture uses this. |
| */ |
| void setFactoryPlayback(SkFlattenable::Factory array[], int count) { |
| fFactoryArray = array; |
| fFactoryCount = count; |
| } |
| |
| /** |
| * For an input flattenable (specified by name), set a custom factory proc |
| * to use when unflattening. Will make a copy of |name|. |
| * |
| * If the global registry already has a default factory for the flattenable, |
| * this will override that factory. If a custom factory has already been |
| * set for the flattenable, this will override that factory. |
| * |
| * Custom factories can be removed by calling setCustomFactory("...", nullptr). |
| */ |
| void setCustomFactory(const SkString& name, SkFlattenable::Factory factory) { |
| fCustomFactory.set(name, factory); |
| } |
| |
| void setDeserialProcs(const SkDeserialProcs& procs); |
| |
| /** |
| * If isValid is false, sets the buffer to be "invalid". Returns true if the buffer |
| * is still valid. |
| */ |
| bool validate(bool isValid) { |
| if (!isValid) { |
| this->setInvalid(); |
| } |
| return !fError; |
| } |
| bool isValid() const { return !fError; } |
| bool validateIndex(int index, int count) { |
| return this->validate(index >= 0 && index < count); |
| } |
| |
| SkInflator* getInflator() const { return fInflator; } |
| void setInflator(SkInflator* inf) { fInflator = inf; } |
| |
| // Utilities that mark the buffer invalid if the requested value is out-of-range |
| |
| // If the read value is outside of the range, validate(false) is called, and min |
| // is returned, else the value is returned. |
| int32_t checkInt(int min, int max); |
| |
| template <typename T> T checkRange(T min, T max) { |
| return static_cast<T>(this->checkInt(static_cast<int32_t>(min), |
| static_cast<int32_t>(max))); |
| } |
| |
| SkFilterQuality checkFilterQuality(); |
| |
| protected: |
| /** |
| * Allows subclass to check if we are using factories for expansion |
| * of flattenables. |
| */ |
| int factoryCount() { return fFactoryCount; } |
| |
| /** |
| * Checks if a custom factory has been set for a given flattenable. |
| * Returns the custom factory if it exists, or nullptr otherwise. |
| */ |
| SkFlattenable::Factory getCustomFactory(const SkString& name) { |
| SkFlattenable::Factory* factoryPtr = fCustomFactory.find(name); |
| return factoryPtr ? *factoryPtr : nullptr; |
| } |
| |
| SkReader32 fReader; |
| |
| // Only used if we do not have an fFactoryArray. |
| SkTHashMap<uint32_t, SkString> fFlattenableDict; |
| |
| private: |
| void setInvalid(); |
| bool readArray(void* value, size_t size, size_t elementSize); |
| void setMemory(const void*, size_t); |
| |
| int fVersion; |
| |
| void* fMemoryPtr; |
| |
| SkTypeface** fTFArray; |
| int fTFCount; |
| |
| SkFlattenable::Factory* fFactoryArray; |
| int fFactoryCount; |
| |
| // Only used if we do not have an fFactoryArray. |
| SkTHashMap<SkString, SkFlattenable::Factory> fCustomFactory; |
| |
| SkDeserialProcs fProcs; |
| friend class SkPicture; |
| |
| #ifdef DEBUG_NON_DETERMINISTIC_ASSERT |
| // Debugging counter to keep track of how many bitmaps we |
| // have decoded. |
| int fDecodedBitmapIndex; |
| #endif // DEBUG_NON_DETERMINISTIC_ASSERT |
| |
| SkInflator* fInflator = nullptr; |
| |
| static bool IsPtrAlign4(const void* ptr) { |
| return SkIsAlign4((uintptr_t)ptr); |
| } |
| |
| bool fError = false; |
| }; |
| |
| #endif // SkReadBuffer_DEFINED |