/* * 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 "SkSerialProcs.h" #include "SkDrawLooper.h" #include "SkImageFilter.h" #include "SkMaskFilterBase.h" #include "SkPaintPriv.h" #include "SkPath.h" #include "SkPathEffect.h" #include "SkPicture.h" #include "SkReader32.h" #include "SkRefCnt.h" #include "SkShaderBase.h" #include "SkTHash.h" #include "SkWriteBuffer.h" class SkData; 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, kDontNegateImageSize_Version = 62, kStoreImageBounds_Version = 63, }; /** * 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() const { return fReader.size(); } size_t offset() const { 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 size_t available() const { return fReader.available(); } template const T* skipT() { return static_cast(this->skip(sizeof(T))); } template const T* skipT(size_t count) { return static_cast(this->skip(count, sizeof(T))); } // primitives bool readBool(); SkColor readColor(); int32_t readInt(); SkScalar readScalar(); uint32_t readUInt(); int32_t read32(); template T read32LE(T max) { uint32_t value = this->readUInt(); if (!this->validate(value <= static_cast(max))) { value = 0; } return static_cast(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 SkPaintPriv::Unflatten(paint, *this); } SkFlattenable* readFlattenable(SkFlattenable::Type); template sk_sp readFlattenable() { return sk_sp((T*)this->readFlattenable(T::GetFlattenableType())); } sk_sp readColorFilter() { return this->readFlattenable(); } sk_sp readDrawLooper() { return this->readFlattenable(); } sk_sp readImageFilter() { return this->readFlattenable(); } sk_sp readMaskFilter() { return this->readFlattenable(); } sk_sp readPathEffect() { return this->readFlattenable(); } sk_sp readShader() { return this->readFlattenable(); } // 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 readByteArrayAsData(); // 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 readImage(); sk_sp readTypeface(); void setTypefaceArray(sk_sp 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; } /** * Helper function to do a preflight check before a large allocation or read. * Returns true if there is enough bytes in the buffer to read n elements of T. * If not, the buffer will be "invalid" and false will be returned. */ template bool validateCanReadN(size_t n) { return this->validate(n <= (fReader.available() / sizeof(T))); } 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 T checkRange(T min, T max) { return static_cast(this->checkInt(static_cast(min), static_cast(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 fFlattenableDict; private: void setInvalid(); bool readArray(void* value, size_t size, size_t elementSize); void setMemory(const void*, size_t); int fVersion; void* fMemoryPtr; sk_sp* fTFArray; int fTFCount; SkFlattenable::Factory* fFactoryArray; int fFactoryCount; // Only used if we do not have an fFactoryArray. SkTHashMap fCustomFactory; SkDeserialProcs fProcs; friend class SkPicturePriv; #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