LP64: Make 9 patches architecture agnostic.

The Res_png_9patch struct had several pointer members
whose size differed between 32 and 64 bit platforms.

These members have been replaced by uint32_t offsets
to serialized data. The serialized form for 9patches
places a Res_png_9patch object at the beginning of
serialized data, followed by int32_t arrays of xDivs,
yDivs and colors.

Note that these offsets are not strictly required,
since they can be computed from the values of numXDivs,
numYDivs & numColors, however they are called in tight
loops so having them computed once is a beneficial.

This change also removed the unused patch_equals function
from aapt's Image.cpp.

Change-Id: I3b9ac8ae5c05510d41377cae4dff1c69b40c2531
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 51f59f6..98849e3 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -118,6 +118,12 @@
     return BAD_TYPE;
 }
 
+static void fill9patchOffsets(Res_png_9patch* patch) {
+    patch->xDivsOffset = sizeof(Res_png_9patch);
+    patch->yDivsOffset = patch->xDivsOffset + (patch->numXDivs * sizeof(int32_t));
+    patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t));
+}
+
 inline void Res_value::copyFrom_dtoh(const Res_value& src)
 {
     size = dtohs(src.size);
@@ -128,9 +134,11 @@
 
 void Res_png_9patch::deviceToFile()
 {
+    int32_t* xDivs = getXDivs();
     for (int i = 0; i < numXDivs; i++) {
         xDivs[i] = htonl(xDivs[i]);
     }
+    int32_t* yDivs = getYDivs();
     for (int i = 0; i < numYDivs; i++) {
         yDivs[i] = htonl(yDivs[i]);
     }
@@ -138,6 +146,7 @@
     paddingRight = htonl(paddingRight);
     paddingTop = htonl(paddingTop);
     paddingBottom = htonl(paddingBottom);
+    uint32_t* colors = getColors();
     for (int i=0; i<numColors; i++) {
         colors[i] = htonl(colors[i]);
     }
@@ -145,9 +154,11 @@
 
 void Res_png_9patch::fileToDevice()
 {
+    int32_t* xDivs = getXDivs();
     for (int i = 0; i < numXDivs; i++) {
         xDivs[i] = ntohl(xDivs[i]);
     }
+    int32_t* yDivs = getYDivs();
     for (int i = 0; i < numYDivs; i++) {
         yDivs[i] = ntohl(yDivs[i]);
     }
@@ -155,60 +166,49 @@
     paddingRight = ntohl(paddingRight);
     paddingTop = ntohl(paddingTop);
     paddingBottom = ntohl(paddingBottom);
+    uint32_t* colors = getColors();
     for (int i=0; i<numColors; i++) {
         colors[i] = ntohl(colors[i]);
     }
 }
 
-size_t Res_png_9patch::serializedSize()
+size_t Res_png_9patch::serializedSize() const
 {
     // The size of this struct is 32 bytes on the 32-bit target system
     // 4 * int8_t
     // 4 * int32_t
-    // 3 * pointer
+    // 3 * uint32_t
     return 32
             + numXDivs * sizeof(int32_t)
             + numYDivs * sizeof(int32_t)
             + numColors * sizeof(uint32_t);
 }
 
-void* Res_png_9patch::serialize()
+void* Res_png_9patch::serialize(const Res_png_9patch& patch, const int32_t* xDivs,
+                                const int32_t* yDivs, const uint32_t* colors)
 {
     // Use calloc since we're going to leave a few holes in the data
     // and want this to run cleanly under valgrind
-    void* newData = calloc(1, serializedSize());
-    serialize(newData);
+    void* newData = calloc(1, patch.serializedSize());
+    serialize(patch, xDivs, yDivs, colors, newData);
     return newData;
 }
 
-void Res_png_9patch::serialize(void * outData)
+void Res_png_9patch::serialize(const Res_png_9patch& patch, const int32_t* xDivs,
+                               const int32_t* yDivs, const uint32_t* colors, void* outData)
 {
-    char* data = (char*) outData;
-    memmove(data, &wasDeserialized, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-    memmove(data + 12, &paddingLeft, 16);   // copy paddingXXXX
+    uint8_t* data = (uint8_t*) outData;
+    memcpy(data, &patch.wasDeserialized, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
+    memcpy(data + 12, &patch.paddingLeft, 16);   // copy paddingXXXX
     data += 32;
 
-    memmove(data, this->xDivs, numXDivs * sizeof(int32_t));
-    data +=  numXDivs * sizeof(int32_t);
-    memmove(data, this->yDivs, numYDivs * sizeof(int32_t));
-    data +=  numYDivs * sizeof(int32_t);
-    memmove(data, this->colors, numColors * sizeof(uint32_t));
-}
+    memcpy(data, xDivs, patch.numXDivs * sizeof(int32_t));
+    data +=  patch.numXDivs * sizeof(int32_t);
+    memcpy(data, yDivs, patch.numYDivs * sizeof(int32_t));
+    data +=  patch.numYDivs * sizeof(int32_t);
+    memcpy(data, colors, patch.numColors * sizeof(uint32_t));
 
-static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
-    char* patch = (char*) inData;
-    if (inData != outData) {
-        memmove(&outData->wasDeserialized, patch, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-        memmove(&outData->paddingLeft, patch + 12, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-    }
-    outData->wasDeserialized = true;
-    char* data = (char*)outData;
-    data +=  sizeof(Res_png_9patch);
-    outData->xDivs = (int32_t*) data;
-    data +=  outData->numXDivs * sizeof(int32_t);
-    outData->yDivs = (int32_t*) data;
-    data +=  outData->numYDivs * sizeof(int32_t);
-    outData->colors = (uint32_t*) data;
+    fill9patchOffsets(reinterpret_cast<Res_png_9patch*>(outData));
 }
 
 static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
@@ -312,14 +312,14 @@
     return NO_ERROR;
 }
 
-Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
+Res_png_9patch* Res_png_9patch::deserialize(void* inData)
 {
-    if (sizeof(void*) != sizeof(int32_t)) {
-        ALOGE("Cannot deserialize on non 32-bit system\n");
-        return NULL;
-    }
-    deserializeInternal(inData, (Res_png_9patch*) inData);
-    return (Res_png_9patch*) inData;
+
+    Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(inData);
+    patch->wasDeserialized = true;
+    fill9patchOffsets(patch);
+
+    return patch;
 }
 
 // --------------------------------------------------------------------
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9b023f9..b2148b0 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -57,7 +57,7 @@
     if (vertices) return vertices;
 
     int8_t emptyQuads = 0;
-    mColors = patch->colors;
+    mColors = patch->getColors();
 
     const int8_t numColors = patch->numColors;
     if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
@@ -79,8 +79,8 @@
     TextureVertex* tempVertices = new TextureVertex[maxVertices];
     TextureVertex* vertex = tempVertices;
 
-    const int32_t* xDivs = patch->xDivs;
-    const int32_t* yDivs = patch->yDivs;
+    const int32_t* xDivs = patch->getXDivs();
+    const int32_t* yDivs = patch->getYDivs();
 
     const uint32_t xStretchCount = (xCount + 1) >> 1;
     const uint32_t yStretchCount = (yCount + 1) >> 1;
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 763a785..b5e8838 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -66,7 +66,7 @@
     void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2, uint32_t& quadCount);
 
-    uint32_t* mColors;
+    const uint32_t* mColors;
     UvMapper mUvMapper;
 }; // struct Patch