Simplify flattening to just write enough to call the factory/public-constructor for the class. We want to *not* rely on private constructors, and not rely on calling through the inheritance hierarchy for either flattening or unflattening(CreateProc).
Refactoring pattern:
1. guard the existing constructor(readbuffer) with the legacy build-flag
2. If you are a instancable subclass, implement CreateProc(readbuffer) to create a new instances from the buffer params (or return NULL).
If you're a shader subclass
1. You must read/write the local matrix if your class accepts that in its factory/constructor, else ignore it.
R=robertphillips@google.com, mtklein@google.com, senorblanco@google.com, senorblanco@chromium.org, sugoi@chromium.org
Author: reed@google.com
Review URL: https://codereview.chromium.org/395603002
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 2544b03..54e1efe 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -61,7 +61,9 @@
};
protected:
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkTable_ColorFilter(SkReadBuffer& buffer);
+#endif
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
private:
@@ -70,6 +72,8 @@
uint8_t fStorage[256 * 4];
unsigned fFlags;
+ friend class SkTableColorFilter;
+
typedef SkColorFilter INHERITED;
};
@@ -168,19 +172,62 @@
#include "SkPackBits.h"
void SkTable_ColorFilter::flatten(SkWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
-
uint8_t storage[5*256];
int count = gCountNibBits[fFlags & 0xF];
size_t size = SkPackBits::Pack8(fStorage, count * 256, storage);
SkASSERT(size <= sizeof(storage));
-// SkDebugf("raw %d packed %d\n", count * 256, size);
-
- buffer.writeInt(fFlags);
+ buffer.write32(fFlags);
buffer.writeByteArray(storage, size);
}
+SkFlattenable* SkTable_ColorFilter::CreateProc(SkReadBuffer& buffer) {
+ const int flags = buffer.read32();
+ const size_t count = gCountNibBits[flags & 0xF];
+ SkASSERT(count <= 4);
+
+ uint8_t packedStorage[5*256];
+ size_t packedSize = buffer.getArrayCount();
+ if (!buffer.validate(packedSize <= sizeof(packedStorage))) {
+ return NULL;
+ }
+ if (!buffer.readByteArray(packedStorage, packedSize)) {
+ return NULL;
+ }
+
+ uint8_t unpackedStorage[4*256];
+ size_t unpackedSize = SkPackBits::Unpack8(packedStorage, packedSize, unpackedStorage);
+ // now check that we got the size we expected
+ if (!buffer.validate(unpackedSize != count*256)) {
+ return NULL;
+ }
+
+ const uint8_t* a = NULL;
+ const uint8_t* r = NULL;
+ const uint8_t* g = NULL;
+ const uint8_t* b = NULL;
+ const uint8_t* ptr = unpackedStorage;
+
+ if (flags & kA_Flag) {
+ a = ptr;
+ ptr += 256;
+ }
+ if (flags & kR_Flag) {
+ r = ptr;
+ ptr += 256;
+ }
+ if (flags & kG_Flag) {
+ g = ptr;
+ ptr += 256;
+ }
+ if (flags & kB_Flag) {
+ b = ptr;
+ ptr += 256;
+ }
+ return SkTableColorFilter::CreateARGB(a, r, g, b);
+}
+
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkTable_ColorFilter::SkTable_ColorFilter(SkReadBuffer& buffer) : INHERITED(buffer) {
fBitmap = NULL;
@@ -199,6 +246,7 @@
SkDEBUGCODE(size_t count = gCountNibBits[fFlags & 0xF]);
SkASSERT(raw == count * 256);
}
+#endif
bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
if (table) {