diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index db11b33a3..38234816c 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -877,9 +877,6 @@ private: unsigned fStyle : 2; unsigned fTextEncoding : 2; // 3 values unsigned fHinting : 2; -#ifdef SK_BUILD_FOR_ANDROID - uint32_t fGenerationID; -#endif SkDrawCacheProc getDrawCacheProc() const; SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir, @@ -905,6 +902,12 @@ private: friend class SkDraw; friend class SkPDFDevice; friend class SkTextToPathIter; + +#ifdef SK_BUILD_FOR_ANDROID + // In order for the == operator to work properly this must be the last field + // in the struct so that we can do a memcmp to this field's offset. + uint32_t fGenerationID; +#endif }; /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 5ed22fd91..ba993486f 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -137,7 +137,12 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { } bool operator==(const SkPaint& a, const SkPaint& b) { +#ifdef SK_BUILD_FOR_ANDROID + //assumes that fGenerationID is the last field in the struct + return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID)); +#else return !memcmp(&a, &b, sizeof(a)); +#endif } void SkPaint::reset() { diff --git a/tests/PaintTest.cpp b/tests/PaintTest.cpp index 361da74e6..6350eb5a6 100644 --- a/tests/PaintTest.cpp +++ b/tests/PaintTest.cpp @@ -8,6 +8,60 @@ #include "Test.h" #include "SkPath.h" #include "SkPaint.h" +#include "SkLayerDrawLooper.h" +#include "SkBlurMaskFilter.h" + +static void test_copy(skiatest::Reporter* reporter) { + SkPaint paint; + // set a few member variables + paint.setStyle(SkPaint::kStrokeAndFill_Style); + paint.setTextAlign(SkPaint::kLeft_Align); + paint.setStrokeWidth(SkIntToScalar(2)); + // set a few pointers + SkLayerDrawLooper* looper = new SkLayerDrawLooper(); + paint.setLooper(looper)->unref(); + SkMaskFilter* mask = SkBlurMaskFilter::Create(1, SkBlurMaskFilter::kNormal_BlurStyle); + paint.setMaskFilter(mask)->unref(); + + // copy the paint using the copy constructor and check they are the same + SkPaint copiedPaint = paint; + REPORTER_ASSERT(reporter, paint == copiedPaint); + +#ifdef SK_BUILD_FOR_ANDROID + // the copy constructor should preserve the Generation ID + int32_t paintGenID = paint.getGenerationID(); + int32_t copiedPaintGenID = copiedPaint.getGenerationID(); + REPORTER_ASSERT(reporter, paintGenID == copiedPaintGenID); + REPORTER_ASSERT(reporter, !memcmp(&paint, &copiedPaint, sizeof(paint))); +#endif + + // copy the paint using the equal operator and check they are the same + copiedPaint = paint; + REPORTER_ASSERT(reporter, paint == copiedPaint); + +#ifdef SK_BUILD_FOR_ANDROID + // the equals operator should increment the Generation ID + REPORTER_ASSERT(reporter, paint.getGenerationID() == paintGenID); + REPORTER_ASSERT(reporter, copiedPaint.getGenerationID() != copiedPaintGenID); + copiedPaintGenID = copiedPaint.getGenerationID(); // reset to the new value + REPORTER_ASSERT(reporter, memcmp(&paint, &copiedPaint, sizeof(paint))); +#endif + + // clean the paint and check they are back to their initial states + SkPaint cleanPaint; + paint.reset(); + copiedPaint.reset(); + REPORTER_ASSERT(reporter, cleanPaint == paint); + REPORTER_ASSERT(reporter, cleanPaint == copiedPaint); + +#ifdef SK_BUILD_FOR_ANDROID + // the reset function should increment the Generation ID + REPORTER_ASSERT(reporter, paint.getGenerationID() != paintGenID); + REPORTER_ASSERT(reporter, copiedPaint.getGenerationID() != copiedPaintGenID); + REPORTER_ASSERT(reporter, memcmp(&cleanPaint, &paint, sizeof(cleanPaint))); + REPORTER_ASSERT(reporter, memcmp(&cleanPaint, &copiedPaint, sizeof(cleanPaint))); +#endif +} // found and fixed for webkit: mishandling when we hit recursion limit on // mostly degenerate cubic flatness test @@ -45,6 +99,7 @@ static void regression_cubic(skiatest::Reporter* reporter) { static void TestPaint(skiatest::Reporter* reporter) { // TODO add general paint tests + test_copy(reporter); // regression tests regression_cubic(reporter);