We don't flatten or unflatten SkPaintOptionsAndroid.  Reproduce and fix.

BUG=skia:1625
R=djsollen@google.com, reed@google.com

Author: mtklein@google.com

Review URL: https://chromiumcodereview.appspot.com/24075010

git-svn-id: http://skia.googlecode.com/svn/trunk@11472 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gyp/core.gyp b/gyp/core.gyp
index 7d322a6..2639ff4 100644
--- a/gyp/core.gyp
+++ b/gyp/core.gyp
@@ -76,9 +76,6 @@
           ],
         }],
         [ 'skia_os == "android"', {
-          'sources': [
-            '../src/core/SkPaintOptionsAndroid.cpp',
-          ],
           'dependencies': [
             'android_deps.gyp:cpu_features',
           ],
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 3b57699..01e5243 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -119,6 +119,7 @@
         '<(skia_src_path)/core/SkOrderedWriteBuffer.cpp',
         '<(skia_src_path)/core/SkPackBits.cpp',
         '<(skia_src_path)/core/SkPaint.cpp',
+        '<(skia_src_path)/core/SkPaintOptionsAndroid.cpp',
         '<(skia_src_path)/core/SkPaintPriv.cpp',
         '<(skia_src_path)/core/SkPaintPriv.h',
         '<(skia_src_path)/core/SkPath.cpp',
diff --git a/gyp/tests.gyp b/gyp/tests.gyp
index c67e578..8b3ceb8 100644
--- a/gyp/tests.gyp
+++ b/gyp/tests.gyp
@@ -22,6 +22,7 @@
       ],
       'sources': [
         '../tests/AAClipTest.cpp',
+        '../tests/AndroidPaintTest.cpp',
         '../tests/AnnotationTest.cpp',
         '../tests/ARGBImageEncoderTest.cpp',
         '../tests/AtomicTest.cpp',
diff --git a/include/core/SkPaintOptionsAndroid.h b/include/core/SkPaintOptionsAndroid.h
index 1bb29f4..f49345f 100644
--- a/include/core/SkPaintOptionsAndroid.h
+++ b/include/core/SkPaintOptionsAndroid.h
@@ -13,8 +13,6 @@
 #include "SkTypes.h"
 #include "SkString.h"
 
-#ifdef SK_BUILD_FOR_ANDROID
-
 class SkFlattenableReadBuffer;
 class SkFlattenableWriteBuffer;
 
@@ -72,6 +70,10 @@
         return *this;
     }
 
+    bool operator==(const SkPaintOptionsAndroid& b) const {
+        return !(*this != b);
+    }
+
     bool operator!=(const SkPaintOptionsAndroid& b) const {
         return fLanguage != b.fLanguage ||
                fFontVariant != b.fFontVariant ||
@@ -125,5 +127,4 @@
     bool fUseFontFallbacks;
 };
 
-#endif // #ifdef SK_BUILD_FOR_ANDROID
 #endif // #ifndef SkPaintOptionsAndroid_DEFINED
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index df8b292..8ca9880 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -21,6 +21,7 @@
 #include "SkOrderedReadBuffer.h"
 #include "SkOrderedWriteBuffer.h"
 #include "SkPaintDefaults.h"
+#include "SkPaintOptionsAndroid.h"
 #include "SkPathEffect.h"
 #include "SkRasterizer.h"
 #include "SkScalar.h"
@@ -2003,8 +2004,9 @@
 }
 
 enum FlatFlags {
-    kHasTypeface_FlatFlag   = 0x01,
-    kHasEffects_FlatFlag    = 0x02,
+    kHasTypeface_FlatFlag                      = 0x01,
+    kHasEffects_FlatFlag                       = 0x02,
+    kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
 };
 
 // The size of a flat paint's POD fields
@@ -2036,7 +2038,11 @@
         asint(this->getImageFilter())) {
         flatFlags |= kHasEffects_FlatFlag;
     }
-
+#if SK_BUILD_FOR_ANDROID
+    if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) {
+        flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag;
+    }
+#endif
 
     if (buffer.isOrderedBinaryBuffer()) {
         SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
@@ -2095,6 +2101,11 @@
         buffer.writeFlattenable(this->getImageFilter());
         buffer.writeFlattenable(this->getAnnotation());
     }
+#if SK_BUILD_FOR_ANDROID
+    if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
+        this->getPaintOptionsAndroid().flatten(buffer);
+    }
+#endif
 }
 
 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
@@ -2180,6 +2191,17 @@
         this->setLooper(NULL);
         this->setImageFilter(NULL);
     }
+
+#if SK_BUILD_FOR_ANDROID
+    this->setPaintOptionsAndroid(SkPaintOptionsAndroid());
+#endif
+    if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
+        SkPaintOptionsAndroid options;
+        options.unflatten(buffer);
+#if SK_BUILD_FOR_ANDROID
+        this->setPaintOptionsAndroid(options);
+#endif
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPaintOptionsAndroid.cpp b/src/core/SkPaintOptionsAndroid.cpp
index 31f489c..f8a65e9 100644
--- a/src/core/SkPaintOptionsAndroid.cpp
+++ b/src/core/SkPaintOptionsAndroid.cpp
@@ -12,14 +12,12 @@
 #include "SkThread.h"
 #include <cstring>
 
-#ifdef SK_BUILD_FOR_ANDROID
-
 SkLanguage SkLanguage::getParent() const {
     SkASSERT(!fTag.isEmpty());
     const char* tag = fTag.c_str();
 
     // strip off the rightmost "-.*"
-    char* parentTagEnd = strrchr(tag, '-');
+    const char* parentTagEnd = strrchr(tag, '-');
     if (parentTagEnd == NULL) {
         return SkLanguage();
     }
@@ -40,5 +38,3 @@
     fLanguage = SkLanguage(tag);
     fUseFontFallbacks = buffer.readBool();
 }
-
-#endif
diff --git a/tests/AndroidPaintTest.cpp b/tests/AndroidPaintTest.cpp
new file mode 100644
index 0000000..07d6e3f
--- /dev/null
+++ b/tests/AndroidPaintTest.cpp
@@ -0,0 +1,81 @@
+// SkPaints only have an SkPaintOptionsAndroid if SK_BUILD_FOR_ANDROID is true.
+#ifdef SK_BUILD_FOR_ANDROID
+
+#include "SkPaintOptionsAndroid.h"
+#include "SkOrderedReadBuffer.h"
+#include "SkOrderedWriteBuffer.h"
+#include "SkPaint.h"
+#include "Test.h"
+#include "TestClassDef.h"
+
+static size_t Reconstruct(const SkPaint& src, SkPaint* dst) {
+    SkOrderedWriteBuffer writer(64 /*arbitrary*/);
+    src.flatten(writer);
+
+    const size_t size = writer.bytesWritten();
+    SkAutoMalloc bytes(size);
+    writer.writeToMemory(bytes.get());
+
+    SkOrderedReadBuffer reader(bytes.get(), size);
+    dst->unflatten(reader);
+
+    return size;
+}
+
+static void android_options_serialization(skiatest::Reporter* reporter) {
+    // We want to make sure that Android's paint options survive a flatten/unflatten round trip.
+    // These are all non-default options.
+    SkPaintOptionsAndroid options;
+    options.setLanguage("ja-JP");
+    options.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant);
+    options.setUseFontFallbacks(true);
+
+    SkPaint paint;
+    paint.setPaintOptionsAndroid(options);
+
+    SkPaint reconstructed;
+    Reconstruct(paint, &reconstructed);
+
+    REPORTER_ASSERT(reporter, options == reconstructed.getPaintOptionsAndroid());
+}
+DEFINE_TESTCLASS_SHORT(android_options_serialization);
+
+static void android_options_serialization_reverse(skiatest::Reporter* reporter) {
+    // Opposite test of above: make sure the serialized default values of a paint overwrite
+    // non-default values on the paint we're unflattening into.
+    const SkPaint defaultOptions;
+
+    SkPaintOptionsAndroid options;
+    options.setLanguage("ja-JP");
+    options.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant);
+    options.setUseFontFallbacks(true);
+    SkPaint nonDefaultOptions;
+    nonDefaultOptions.setPaintOptionsAndroid(options);
+
+    Reconstruct(defaultOptions, &nonDefaultOptions);
+
+    REPORTER_ASSERT(reporter,
+            defaultOptions.getPaintOptionsAndroid() ==
+            nonDefaultOptions.getPaintOptionsAndroid());
+}
+DEFINE_TESTCLASS_SHORT(android_options_serialization_reverse);
+
+static void android_options_size(skiatest::Reporter* reporter) {
+    // A paint with default android options should serialize to something smaller than
+    // a paint with non-default android options.
+
+    SkPaint defaultOptions;
+
+    SkPaintOptionsAndroid options;
+    options.setUseFontFallbacks(true);
+    SkPaint nonDefaultOptions;
+    nonDefaultOptions.setPaintOptionsAndroid(options);
+
+    SkPaint dummy;
+
+    REPORTER_ASSERT(reporter,
+                    Reconstruct(defaultOptions, &dummy) < Reconstruct(nonDefaultOptions, &dummy));
+}
+DEFINE_TESTCLASS_SHORT(android_options_size);
+
+#endif  // SK_BUILD_FOR_ANDROID