Pipe factory names independently from the flattenables using them.

Avoids an issue where a flattenable written twice might be written
differently (the first time the flat data may have a name, whereas
the second time it will have an index).

Also add a test which confirms that identical flattenables will have
the same SkFlatData representation.

BUG=https://code.google.com/p/skia/issues/detail?id=721
TEST=FlatDataTest.cpp

Review URL: https://codereview.appspot.com/6431057

git-svn-id: http://skia.googlecode.com/svn/trunk@4896 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/FlatDataTest.cpp b/tests/FlatDataTest.cpp
new file mode 100644
index 0000000..755d8cd
--- /dev/null
+++ b/tests/FlatDataTest.cpp
@@ -0,0 +1,85 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkColorFilter.h"
+#include "SkGradientShader.h"
+#include "SkPaint.h"
+#include "SkPictureFlat.h"
+#include "SkShader.h"
+#include "SkXfermode.h"
+#include "Test.h"
+
+static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer,
+                                   const void* obj) {
+    buffer.writeFlattenable((SkFlattenable*)obj);
+}
+
+/**
+ * Verify that two SkFlatData objects that created from the same object are
+ * identical when using an SkNamedFactorySet.
+ * @param reporter Object to report failures.
+ * @param obj Flattenable object to be flattened.
+ * @param flattenProc Function that flattens objects with the same type as obj.
+ */
+static void testCreate(skiatest::Reporter* reporter, const void* obj,
+                       void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) {
+    SkChunkFlatController controller(1024);
+    SkNamedFactorySet factorySet;
+    // No need to delete data because that will be taken care of by the
+    // controller.
+    SkFlatData* data1 = SkFlatData::Create(&controller, obj, 0, flattenProc,
+                                           NULL, NULL, 0, &factorySet);
+    data1->setSentinelInCache();
+    SkFlatData* data2 = SkFlatData::Create(&controller, obj, 0, flattenProc,
+                                           NULL, NULL, 0, &factorySet);
+    data2->setSentinelAsCandidate();
+    REPORTER_ASSERT(reporter, SkFlatData::Compare(data1, data2) == 0);
+}
+
+static void Tests(skiatest::Reporter* reporter) {
+    // Test flattening SkShader
+    SkPoint points[2];
+    points[0].set(0, 0);
+    points[1].set(SkIntToScalar(20), SkIntToScalar(20));
+    SkColor colors[2];
+    colors[0] = SK_ColorRED;
+    colors[1] = SK_ColorBLUE;
+    SkShader* shader = SkGradientShader::CreateLinear(points, colors, NULL,
+                                            2, SkShader::kRepeat_TileMode);
+    SkAutoUnref aur(shader);
+    testCreate(reporter, shader, flattenFlattenableProc);
+
+    // Test SkBitmap
+    {
+        SkBitmap bm;
+        bm.setConfig(SkBitmap::kARGB_8888_Config, 50, 50);
+        bm.allocPixels();
+        SkCanvas canvas(bm);
+        SkPaint paint;
+        paint.setShader(shader);
+        canvas.drawPaint(paint);
+        testCreate(reporter, &bm, &SkFlattenObjectProc<SkBitmap>);
+    }
+
+    // Test SkColorFilter
+    SkColorFilter* cf = SkColorFilter::CreateLightingFilter(SK_ColorBLUE,
+                                                            SK_ColorRED);
+    SkAutoUnref aurcf(cf);
+    testCreate(reporter, cf, &flattenFlattenableProc);
+
+    // Test SkXfermode
+    SkXfermode* xfer = SkXfermode::Create(SkXfermode::kDstOver_Mode);
+    SkAutoUnref aurxf(xfer);
+    testCreate(reporter, xfer, &flattenFlattenableProc);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("FlatData", FlatDataClass, Tests)