factor out flattening/unflattening of common fields from SkImageFilter

This is a precursor to changing SkImageFilters (and all effects) to unflatten via a factory instead of a constructor. In that world, each subclass of ImageFilter will need to control/initiate the unflattening of the common fields, so they can be extract and passed to their Factory.

R=senorblanco@google.com, robertphillips@google.com, mtklein@google.com, senorblanco@chromium.org

Author: reed@google.com

Review URL: https://codereview.chromium.org/395273002
This commit is contained in:
reed 2014-07-17 07:03:09 -07:00 committed by Commit bot
parent 3eb258d3f6
commit b959ec7815
2 changed files with 81 additions and 20 deletions

View File

@ -11,6 +11,7 @@
#include "SkFlattenable.h"
#include "SkMatrix.h"
#include "SkRect.h"
#include "SkTemplates.h"
class SkBitmap;
class SkColorFilter;
@ -199,6 +200,31 @@ public:
SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
protected:
class Common {
public:
Common() {}
~Common();
bool unflatten(SkReadBuffer&, int expectedInputs = -1);
CropRect cropRect() const { return fCropRect; }
int inputCount() const { return fInputs.count(); }
SkImageFilter** inputs() const { return fInputs.get(); }
// If the caller wants a copy of the inputs, call this and it will transfer ownership
// of the unflattened input filters to the caller. This is just a short-cut for copying
// the inputs, calling ref() on each, and then waiting for Common's destructor to call
// unref() on each.
void detachInputs(SkImageFilter** inputs);
private:
CropRect fCropRect;
// most filters accept at most 2 input-filters
SkAutoSTArray<2, SkImageFilter*> fInputs;
void allocInputs(int count);
};
SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
virtual ~SkImageFilter();

View File

@ -21,6 +21,55 @@
#include "SkGr.h"
#endif
SkImageFilter::Common::~Common() {
for (int i = 0; i < fInputs.count(); ++i) {
SkSafeUnref(fInputs[i]);
}
}
void SkImageFilter::Common::allocInputs(int count) {
const size_t size = count * sizeof(SkImageFilter*);
fInputs.reset(count);
sk_bzero(fInputs.get(), size);
}
void SkImageFilter::Common::detachInputs(SkImageFilter** inputs) {
const size_t size = fInputs.count() * sizeof(SkImageFilter*);
memcpy(inputs, fInputs.get(), size);
sk_bzero(fInputs.get(), size);
}
bool SkImageFilter::Common::unflatten(SkReadBuffer& buffer, int expectedCount) {
int count = buffer.readInt();
if (expectedCount < 0) { // means the caller doesn't care how many
expectedCount = count;
}
if (!buffer.validate(count == expectedCount)) {
return false;
}
this->allocInputs(count);
for (int i = 0; i < count; i++) {
if (buffer.readBool()) {
fInputs[i] = buffer.readImageFilter();
}
if (!buffer.isValid()) {
return false;
}
}
SkRect rect;
buffer.readRect(&rect);
if (!buffer.isValid() || !buffer.validate(SkIsValidRect(rect))) {
return false;
}
uint32_t flags = buffer.readUInt();
fCropRect = CropRect(rect, flags);
return buffer.isValid();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
SkImageFilter::Cache* gExternalCache;
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
@ -41,26 +90,12 @@ SkImageFilter::~SkImageFilter() {
}
SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) {
fInputCount = buffer.readInt();
if (buffer.validate((fInputCount >= 0) && ((inputCount < 0) || (fInputCount == inputCount)))) {
fInputs = new SkImageFilter*[fInputCount];
for (int i = 0; i < fInputCount; i++) {
if (buffer.readBool()) {
fInputs[i] = buffer.readImageFilter();
} else {
fInputs[i] = NULL;
}
if (!buffer.isValid()) {
fInputCount = i; // Do not use fInputs past that point in the destructor
break;
}
}
SkRect rect;
buffer.readRect(&rect);
if (buffer.isValid() && buffer.validate(SkIsValidRect(rect))) {
uint32_t flags = buffer.readUInt();
fCropRect = CropRect(rect, flags);
}
Common common;
if (common.unflatten(buffer, inputCount)) {
fCropRect = common.cropRect();
fInputCount = common.inputCount();
fInputs = SkNEW_ARRAY(SkImageFilter*, fInputCount);
common.detachInputs(fInputs);
} else {
fInputCount = 0;
fInputs = NULL;