| Index: src/gpu/GrShape.cpp
|
| diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
|
| index 582858e1d9608b506669ecb3ee9ae7a9c5c4c55d..b3c1e0a4cc7315f09f6588849f4c3c48d71edbc9 100644
|
| --- a/src/gpu/GrShape.cpp
|
| +++ b/src/gpu/GrShape.cpp
|
| @@ -72,6 +72,49 @@ SkRect GrShape::styledBounds() const {
|
| return bounds;
|
| }
|
|
|
| +// If the path is small enough to be keyed from its data this returns key length, otherwise -1.
|
| +static int path_key_from_data_size(const SkPath& path) {
|
| + const int verbCnt = path.countVerbs();
|
| + if (verbCnt > GrShape::kMaxKeyFromDataVerbCnt) {
|
| + return -1;
|
| + }
|
| + const int pointCnt = path.countPoints();
|
| + const int conicWeightCnt = SkPathPriv::ConicWeightCnt(path);
|
| +
|
| + GR_STATIC_ASSERT(sizeof(SkPoint) == 2 * sizeof(uint32_t));
|
| + GR_STATIC_ASSERT(sizeof(SkScalar) == sizeof(uint32_t));
|
| + // 2 is for the verb cnt and a fill type. Each verb is a byte but we'll pad the verb data out to
|
| + // a uint32_t length.
|
| + return 2 + (SkAlign4(verbCnt) >> 2) + 2 * pointCnt + conicWeightCnt;
|
| +}
|
| +
|
| +// Writes the path data key into the passed pointer.
|
| +static void write_path_key_from(const SkPath& path, uint32_t* origKey) {
|
| + uint32_t* key = origKey;
|
| + // The check below should take care of negative values casted positive.
|
| + const int verbCnt = path.countVerbs();
|
| + const int pointCnt = path.countPoints();
|
| + const int conicWeightCnt = SkPathPriv::ConicWeightCnt(path);
|
| + SkASSERT(verbCnt <= GrShape::kMaxKeyFromDataVerbCnt);
|
| + SkASSERT(pointCnt && verbCnt);
|
| + *key++ = path.getFillType();
|
| + *key++ = verbCnt;
|
| + memcpy(key, SkPathPriv::VerbData(path), verbCnt * sizeof(uint8_t));
|
| + int verbKeySize = SkAlign4(verbCnt);
|
| + // pad out to uint32_t alignment using value that will stand out when debugging.
|
| + uint8_t* pad = reinterpret_cast<uint8_t*>(key)+ verbCnt;
|
| + memset(pad, 0xDE, verbKeySize - verbCnt);
|
| + key += verbKeySize >> 2;
|
| +
|
| + memcpy(key, SkPathPriv::PointData(path), sizeof(SkPoint) * pointCnt);
|
| + GR_STATIC_ASSERT(sizeof(SkPoint) == 2 * sizeof(uint32_t));
|
| + key += 2 * pointCnt;
|
| + memcpy(key, SkPathPriv::ConicWeightData(path), sizeof(SkScalar) * conicWeightCnt);
|
| + GR_STATIC_ASSERT(sizeof(SkScalar) == sizeof(uint32_t));
|
| + SkDEBUGCODE(key += conicWeightCnt);
|
| + SkASSERT(key - origKey == path_key_from_data_size(path));
|
| +}
|
| +
|
| int GrShape::unstyledKeySize() const {
|
| if (fInheritedKey.count()) {
|
| return fInheritedKey.count();
|
| @@ -88,13 +131,17 @@ int GrShape::unstyledKeySize() const {
|
| GR_STATIC_ASSERT(2 * sizeof(uint32_t) == sizeof(SkPoint));
|
| // 4 for the end points and 1 for the inverseness
|
| return 5;
|
| - case Type::kPath:
|
| + case Type::kPath: {
|
| + int dataKeySize = path_key_from_data_size(fPathData.fPath);
|
| + if (dataKeySize >= 0) {
|
| + return dataKeySize;
|
| + }
|
| if (0 == fPathData.fGenID) {
|
| return -1;
|
| - } else {
|
| - // The key is the path ID and fill type.
|
| - return 2;
|
| }
|
| + // The key is the path ID and fill type.
|
| + return 2;
|
| + }
|
| }
|
| SkFAIL("Should never get here.");
|
| return 0;
|
| @@ -124,13 +171,19 @@ void GrShape::writeUnstyledKey(uint32_t* key) const {
|
| key += 4;
|
| *key++ = fLineData.fInverted ? 1 : 0;
|
| break;
|
| - case Type::kPath:
|
| + case Type::kPath: {
|
| + int dataKeySize = path_key_from_data_size(fPathData.fPath);
|
| + if (dataKeySize >= 0) {
|
| + write_path_key_from(fPathData.fPath, key);
|
| + return;
|
| + }
|
| SkASSERT(fPathData.fGenID);
|
| *key++ = fPathData.fGenID;
|
| // We could canonicalize the fill rule for paths that don't differentiate between
|
| // even/odd or winding fill (e.g. convex).
|
| *key++ = this->path().getFillType();
|
| break;
|
| + }
|
| }
|
| }
|
| SkASSERT(key - origKey == this->unstyledKeySize());
|
|
|