* commit '8272c84cb531a4f148f0b0a31d8359d381137378': LP64: Make 9 patches architecture agnostic.
This commit is contained in:
@ -106,17 +106,19 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) {
|
|||||||
chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f);
|
chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f);
|
||||||
chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f);
|
chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f);
|
||||||
|
|
||||||
|
int32_t* xDivs = chunk->getXDivs();
|
||||||
for (int i = 0; i < chunk->numXDivs; i++) {
|
for (int i = 0; i < chunk->numXDivs; i++) {
|
||||||
chunk->xDivs[i] = int(chunk->xDivs[i] * scale + 0.5f);
|
xDivs[i] = int32_t(xDivs[i] * scale + 0.5f);
|
||||||
if (i > 0 && chunk->xDivs[i] == chunk->xDivs[i - 1]) {
|
if (i > 0 && xDivs[i] == xDivs[i - 1]) {
|
||||||
chunk->xDivs[i]++;
|
xDivs[i]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t* yDivs = chunk->getXDivs();
|
||||||
for (int i = 0; i < chunk->numYDivs; i++) {
|
for (int i = 0; i < chunk->numYDivs; i++) {
|
||||||
chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);
|
yDivs[i] = int32_t(yDivs[i] * scale + 0.5f);
|
||||||
if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) {
|
if (i > 0 && yDivs[i] == yDivs[i - 1]) {
|
||||||
chunk->yDivs[i]++;
|
yDivs[i]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,7 +367,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
|||||||
return nullObjectReturn("primitive array == null");
|
return nullObjectReturn("primitive array == null");
|
||||||
}
|
}
|
||||||
|
|
||||||
peeker.fPatch->serialize(array);
|
memcpy(array, peeker.fPatch, peeker.fPatchSize);
|
||||||
env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
|
env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,12 +116,14 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
|
|||||||
paint = &defaultPaint;
|
paint = &defaultPaint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int32_t* xDivs = chunk.getXDivs();
|
||||||
|
const int32_t* yDivs = chunk.getYDivs();
|
||||||
// if our SkCanvas were back by GL we should enable this and draw this as
|
// if our SkCanvas were back by GL we should enable this and draw this as
|
||||||
// a mesh, which will be faster in most cases.
|
// a mesh, which will be faster in most cases.
|
||||||
if (false) {
|
if (false) {
|
||||||
SkNinePatch::DrawMesh(canvas, bounds, bitmap,
|
SkNinePatch::DrawMesh(canvas, bounds, bitmap,
|
||||||
chunk.xDivs, chunk.numXDivs,
|
xDivs, chunk.numXDivs,
|
||||||
chunk.yDivs, chunk.numYDivs,
|
yDivs, chunk.numYDivs,
|
||||||
paint);
|
paint);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -145,8 +147,8 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
|
|||||||
if (gTrace) {
|
if (gTrace) {
|
||||||
ALOGV("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()));
|
ALOGV("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()));
|
||||||
ALOGV("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height());
|
ALOGV("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height());
|
||||||
ALOGV("======== ninepatch xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]);
|
ALOGV("======== ninepatch xDivs [%d,%d]\n", xDivs[0], xDivs[1]);
|
||||||
ALOGV("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]);
|
ALOGV("======== ninepatch yDivs [%d,%d]\n", yDivs[0], yDivs[1]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -171,8 +173,8 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
|
|||||||
SkRect dst;
|
SkRect dst;
|
||||||
SkIRect src;
|
SkIRect src;
|
||||||
|
|
||||||
const int32_t x0 = chunk.xDivs[0];
|
const int32_t x0 = xDivs[0];
|
||||||
const int32_t y0 = chunk.yDivs[0];
|
const int32_t y0 = yDivs[0];
|
||||||
const SkColor initColor = ((SkPaint*)paint)->getColor();
|
const SkColor initColor = ((SkPaint*)paint)->getColor();
|
||||||
const uint8_t numXDivs = chunk.numXDivs;
|
const uint8_t numXDivs = chunk.numXDivs;
|
||||||
const uint8_t numYDivs = chunk.numYDivs;
|
const uint8_t numYDivs = chunk.numYDivs;
|
||||||
@ -191,12 +193,12 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
|
|||||||
|
|
||||||
int numStretchyXPixelsRemaining = 0;
|
int numStretchyXPixelsRemaining = 0;
|
||||||
for (i = 0; i < numXDivs; i += 2) {
|
for (i = 0; i < numXDivs; i += 2) {
|
||||||
numStretchyXPixelsRemaining += chunk.xDivs[i + 1] - chunk.xDivs[i];
|
numStretchyXPixelsRemaining += xDivs[i + 1] - xDivs[i];
|
||||||
}
|
}
|
||||||
int numFixedXPixelsRemaining = bitmapWidth - numStretchyXPixelsRemaining;
|
int numFixedXPixelsRemaining = bitmapWidth - numStretchyXPixelsRemaining;
|
||||||
int numStretchyYPixelsRemaining = 0;
|
int numStretchyYPixelsRemaining = 0;
|
||||||
for (i = 0; i < numYDivs; i += 2) {
|
for (i = 0; i < numYDivs; i += 2) {
|
||||||
numStretchyYPixelsRemaining += chunk.yDivs[i + 1] - chunk.yDivs[i];
|
numStretchyYPixelsRemaining += yDivs[i + 1] - yDivs[i];
|
||||||
}
|
}
|
||||||
int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining;
|
int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining;
|
||||||
|
|
||||||
@ -235,7 +237,7 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
|
|||||||
src.fBottom = bitmapHeight;
|
src.fBottom = bitmapHeight;
|
||||||
dst.fBottom = bounds.fBottom;
|
dst.fBottom = bounds.fBottom;
|
||||||
} else {
|
} else {
|
||||||
src.fBottom = chunk.yDivs[j];
|
src.fBottom = yDivs[j];
|
||||||
const int srcYSize = src.fBottom - src.fTop;
|
const int srcYSize = src.fBottom - src.fTop;
|
||||||
if (yIsStretchable) {
|
if (yIsStretchable) {
|
||||||
dst.fBottom = dst.fTop + calculateStretch(bounds.fBottom, dst.fTop,
|
dst.fBottom = dst.fTop + calculateStretch(bounds.fBottom, dst.fTop,
|
||||||
@ -252,15 +254,16 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
|
|||||||
xIsStretchable = initialXIsStretchable;
|
xIsStretchable = initialXIsStretchable;
|
||||||
// The initial xDiv and whether the first column is considered
|
// The initial xDiv and whether the first column is considered
|
||||||
// stretchable or not depends on whether xDiv[0] was zero or not.
|
// stretchable or not depends on whether xDiv[0] was zero or not.
|
||||||
|
const uint32_t* colors = chunk.getColors();
|
||||||
for (i = xIsStretchable ? 1 : 0;
|
for (i = xIsStretchable ? 1 : 0;
|
||||||
i <= numXDivs && src.fLeft < bitmapWidth;
|
i <= numXDivs && src.fLeft < bitmapWidth;
|
||||||
i++, xIsStretchable = !xIsStretchable) {
|
i++, xIsStretchable = !xIsStretchable) {
|
||||||
color = chunk.colors[colorIndex++];
|
color = colors[colorIndex++];
|
||||||
if (i == numXDivs) {
|
if (i == numXDivs) {
|
||||||
src.fRight = bitmapWidth;
|
src.fRight = bitmapWidth;
|
||||||
dst.fRight = bounds.fRight;
|
dst.fRight = bounds.fRight;
|
||||||
} else {
|
} else {
|
||||||
src.fRight = chunk.xDivs[i];
|
src.fRight = xDivs[i];
|
||||||
if (dstRightsHaveBeenCached) {
|
if (dstRightsHaveBeenCached) {
|
||||||
dst.fRight = dstRights[i];
|
dst.fRight = dstRights[i];
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,11 +28,11 @@ bool NinePatchPeeker::peek(const char tag[], const void* data, size_t length) {
|
|||||||
// You have to copy the data because it is owned by the png reader
|
// You have to copy the data because it is owned by the png reader
|
||||||
Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
|
Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
|
||||||
memcpy(patchNew, patch, patchSize);
|
memcpy(patchNew, patch, patchSize);
|
||||||
// this relies on deserialization being done in place
|
|
||||||
Res_png_9patch::deserialize(patchNew);
|
Res_png_9patch::deserialize(patchNew);
|
||||||
patchNew->fileToDevice();
|
patchNew->fileToDevice();
|
||||||
free(fPatch);
|
free(fPatch);
|
||||||
fPatch = patchNew;
|
fPatch = patchNew;
|
||||||
|
fPatchSize = patchSize;
|
||||||
//printf("9patch: (%d,%d)-(%d,%d)\n",
|
//printf("9patch: (%d,%d)-(%d,%d)\n",
|
||||||
// fPatch.sizeLeft, fPatch.sizeTop,
|
// fPatch.sizeLeft, fPatch.sizeTop,
|
||||||
// fPatch.sizeRight, fPatch.sizeBottom);
|
// fPatch.sizeRight, fPatch.sizeBottom);
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
// the host lives longer than we do, so a raw ptr is safe
|
// the host lives longer than we do, so a raw ptr is safe
|
||||||
fHost = host;
|
fHost = host;
|
||||||
fPatch = NULL;
|
fPatch = NULL;
|
||||||
|
fPatchSize = 0;
|
||||||
fLayoutBounds = NULL;
|
fLayoutBounds = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Res_png_9patch* fPatch;
|
Res_png_9patch* fPatch;
|
||||||
|
size_t fPatchSize;
|
||||||
int *fLayoutBounds;
|
int *fLayoutBounds;
|
||||||
|
|
||||||
virtual bool peek(const char tag[], const void* data, size_t length);
|
virtual bool peek(const char tag[], const void* data, size_t length);
|
||||||
|
@ -79,7 +79,7 @@ namespace android {
|
|||||||
* two stretchable slices is exactly the ratio of their corresponding
|
* two stretchable slices is exactly the ratio of their corresponding
|
||||||
* segment lengths.
|
* segment lengths.
|
||||||
*
|
*
|
||||||
* xDivs and yDivs point to arrays of horizontal and vertical pixel
|
* xDivs and yDivs are arrays of horizontal and vertical pixel
|
||||||
* indices. The first pair of Divs (in either array) indicate the
|
* indices. The first pair of Divs (in either array) indicate the
|
||||||
* starting and ending points of the first stretchable segment in that
|
* starting and ending points of the first stretchable segment in that
|
||||||
* axis. The next pair specifies the next stretchable segment, etc. So
|
* axis. The next pair specifies the next stretchable segment, etc. So
|
||||||
@ -92,32 +92,31 @@ namespace android {
|
|||||||
* go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
|
* go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
|
||||||
* xDiv[2].
|
* xDiv[2].
|
||||||
*
|
*
|
||||||
* The array pointed to by the colors field lists contains hints for
|
* The colors array contains hints for each of the regions. They are
|
||||||
* each of the regions. They are ordered according left-to-right and
|
* ordered according left-to-right and top-to-bottom as indicated above.
|
||||||
* top-to-bottom as indicated above. For each segment that is a solid
|
* For each segment that is a solid color the array entry will contain
|
||||||
* color the array entry will contain that color value; otherwise it
|
* that color value; otherwise it will contain NO_COLOR. Segments that
|
||||||
* will contain NO_COLOR. Segments that are completely transparent
|
* are completely transparent will always have the value TRANSPARENT_COLOR.
|
||||||
* will always have the value TRANSPARENT_COLOR.
|
|
||||||
*
|
*
|
||||||
* The PNG chunk type is "npTc".
|
* The PNG chunk type is "npTc".
|
||||||
*/
|
*/
|
||||||
struct Res_png_9patch
|
struct Res_png_9patch
|
||||||
{
|
{
|
||||||
Res_png_9patch() : wasDeserialized(false), xDivs(NULL),
|
Res_png_9patch() : wasDeserialized(false), xDivsOffset(0),
|
||||||
yDivs(NULL), colors(NULL) { }
|
yDivsOffset(0), colorsOffset(0) { }
|
||||||
|
|
||||||
int8_t wasDeserialized;
|
int8_t wasDeserialized;
|
||||||
int8_t numXDivs;
|
int8_t numXDivs;
|
||||||
int8_t numYDivs;
|
int8_t numYDivs;
|
||||||
int8_t numColors;
|
int8_t numColors;
|
||||||
|
|
||||||
// These tell where the next section of a patch starts.
|
// The offset (from the start of this structure) to the xDivs & yDivs
|
||||||
// For example, the first patch includes the pixels from
|
// array for this 9patch. To get a pointer to this array, call
|
||||||
// 0 to xDivs[0]-1 and the second patch includes the pixels
|
// getXDivs or getYDivs. Note that the serialized form for 9patches places
|
||||||
// from xDivs[0] to xDivs[1]-1.
|
// the xDivs, yDivs and colors arrays immediately after the location
|
||||||
// Note: allocation/free of these pointers is left to the caller.
|
// of the Res_png_9patch struct.
|
||||||
int32_t* xDivs;
|
uint32_t xDivsOffset;
|
||||||
int32_t* yDivs;
|
uint32_t yDivsOffset;
|
||||||
|
|
||||||
int32_t paddingLeft, paddingRight;
|
int32_t paddingLeft, paddingRight;
|
||||||
int32_t paddingTop, paddingBottom;
|
int32_t paddingTop, paddingBottom;
|
||||||
@ -129,22 +128,42 @@ struct Res_png_9patch
|
|||||||
// The 9 patch segment is completely transparent.
|
// The 9 patch segment is completely transparent.
|
||||||
TRANSPARENT_COLOR = 0x00000000
|
TRANSPARENT_COLOR = 0x00000000
|
||||||
};
|
};
|
||||||
// Note: allocation/free of this pointer is left to the caller.
|
|
||||||
uint32_t* colors;
|
// The offset (from the start of this structure) to the colors array
|
||||||
|
// for this 9patch.
|
||||||
|
uint32_t colorsOffset;
|
||||||
|
|
||||||
// Convert data from device representation to PNG file representation.
|
// Convert data from device representation to PNG file representation.
|
||||||
void deviceToFile();
|
void deviceToFile();
|
||||||
// Convert data from PNG file representation to device representation.
|
// Convert data from PNG file representation to device representation.
|
||||||
void fileToDevice();
|
void fileToDevice();
|
||||||
// Serialize/Marshall the patch data into a newly malloc-ed block
|
|
||||||
void* serialize();
|
// Serialize/Marshall the patch data into a newly malloc-ed block.
|
||||||
// Serialize/Marshall the patch data
|
static void* serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs,
|
||||||
void serialize(void* outData);
|
const int32_t* yDivs, const uint32_t* colors);
|
||||||
|
// Serialize/Marshall the patch data into |outData|.
|
||||||
|
static void serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs,
|
||||||
|
const int32_t* yDivs, const uint32_t* colors, void* outData);
|
||||||
// Deserialize/Unmarshall the patch data
|
// Deserialize/Unmarshall the patch data
|
||||||
static Res_png_9patch* deserialize(const void* data);
|
static Res_png_9patch* deserialize(void* data);
|
||||||
// Compute the size of the serialized data structure
|
// Compute the size of the serialized data structure
|
||||||
size_t serializedSize();
|
size_t serializedSize() const;
|
||||||
};
|
|
||||||
|
// These tell where the next section of a patch starts.
|
||||||
|
// For example, the first patch includes the pixels from
|
||||||
|
// 0 to xDivs[0]-1 and the second patch includes the pixels
|
||||||
|
// from xDivs[0] to xDivs[1]-1.
|
||||||
|
inline int32_t* getXDivs() const {
|
||||||
|
return reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(this) + xDivsOffset);
|
||||||
|
}
|
||||||
|
inline int32_t* getYDivs() const {
|
||||||
|
return reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(this) + yDivsOffset);
|
||||||
|
}
|
||||||
|
inline uint32_t* getColors() const {
|
||||||
|
return reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(this) + colorsOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/** ********************************************************************
|
/** ********************************************************************
|
||||||
* Base Types
|
* Base Types
|
||||||
|
@ -118,6 +118,12 @@ static status_t validate_chunk(const ResChunk_header* chunk,
|
|||||||
return BAD_TYPE;
|
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)
|
inline void Res_value::copyFrom_dtoh(const Res_value& src)
|
||||||
{
|
{
|
||||||
size = dtohs(src.size);
|
size = dtohs(src.size);
|
||||||
@ -128,9 +134,11 @@ inline void Res_value::copyFrom_dtoh(const Res_value& src)
|
|||||||
|
|
||||||
void Res_png_9patch::deviceToFile()
|
void Res_png_9patch::deviceToFile()
|
||||||
{
|
{
|
||||||
|
int32_t* xDivs = getXDivs();
|
||||||
for (int i = 0; i < numXDivs; i++) {
|
for (int i = 0; i < numXDivs; i++) {
|
||||||
xDivs[i] = htonl(xDivs[i]);
|
xDivs[i] = htonl(xDivs[i]);
|
||||||
}
|
}
|
||||||
|
int32_t* yDivs = getYDivs();
|
||||||
for (int i = 0; i < numYDivs; i++) {
|
for (int i = 0; i < numYDivs; i++) {
|
||||||
yDivs[i] = htonl(yDivs[i]);
|
yDivs[i] = htonl(yDivs[i]);
|
||||||
}
|
}
|
||||||
@ -138,6 +146,7 @@ void Res_png_9patch::deviceToFile()
|
|||||||
paddingRight = htonl(paddingRight);
|
paddingRight = htonl(paddingRight);
|
||||||
paddingTop = htonl(paddingTop);
|
paddingTop = htonl(paddingTop);
|
||||||
paddingBottom = htonl(paddingBottom);
|
paddingBottom = htonl(paddingBottom);
|
||||||
|
uint32_t* colors = getColors();
|
||||||
for (int i=0; i<numColors; i++) {
|
for (int i=0; i<numColors; i++) {
|
||||||
colors[i] = htonl(colors[i]);
|
colors[i] = htonl(colors[i]);
|
||||||
}
|
}
|
||||||
@ -145,9 +154,11 @@ void Res_png_9patch::deviceToFile()
|
|||||||
|
|
||||||
void Res_png_9patch::fileToDevice()
|
void Res_png_9patch::fileToDevice()
|
||||||
{
|
{
|
||||||
|
int32_t* xDivs = getXDivs();
|
||||||
for (int i = 0; i < numXDivs; i++) {
|
for (int i = 0; i < numXDivs; i++) {
|
||||||
xDivs[i] = ntohl(xDivs[i]);
|
xDivs[i] = ntohl(xDivs[i]);
|
||||||
}
|
}
|
||||||
|
int32_t* yDivs = getYDivs();
|
||||||
for (int i = 0; i < numYDivs; i++) {
|
for (int i = 0; i < numYDivs; i++) {
|
||||||
yDivs[i] = ntohl(yDivs[i]);
|
yDivs[i] = ntohl(yDivs[i]);
|
||||||
}
|
}
|
||||||
@ -155,60 +166,49 @@ void Res_png_9patch::fileToDevice()
|
|||||||
paddingRight = ntohl(paddingRight);
|
paddingRight = ntohl(paddingRight);
|
||||||
paddingTop = ntohl(paddingTop);
|
paddingTop = ntohl(paddingTop);
|
||||||
paddingBottom = ntohl(paddingBottom);
|
paddingBottom = ntohl(paddingBottom);
|
||||||
|
uint32_t* colors = getColors();
|
||||||
for (int i=0; i<numColors; i++) {
|
for (int i=0; i<numColors; i++) {
|
||||||
colors[i] = ntohl(colors[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
|
// The size of this struct is 32 bytes on the 32-bit target system
|
||||||
// 4 * int8_t
|
// 4 * int8_t
|
||||||
// 4 * int32_t
|
// 4 * int32_t
|
||||||
// 3 * pointer
|
// 3 * uint32_t
|
||||||
return 32
|
return 32
|
||||||
+ numXDivs * sizeof(int32_t)
|
+ numXDivs * sizeof(int32_t)
|
||||||
+ numYDivs * sizeof(int32_t)
|
+ numYDivs * sizeof(int32_t)
|
||||||
+ numColors * sizeof(uint32_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
|
// Use calloc since we're going to leave a few holes in the data
|
||||||
// and want this to run cleanly under valgrind
|
// and want this to run cleanly under valgrind
|
||||||
void* newData = calloc(1, serializedSize());
|
void* newData = calloc(1, patch.serializedSize());
|
||||||
serialize(newData);
|
serialize(patch, xDivs, yDivs, colors, newData);
|
||||||
return 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;
|
uint8_t* data = (uint8_t*) outData;
|
||||||
memmove(data, &wasDeserialized, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
|
memcpy(data, &patch.wasDeserialized, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
|
||||||
memmove(data + 12, &paddingLeft, 16); // copy paddingXXXX
|
memcpy(data + 12, &patch.paddingLeft, 16); // copy paddingXXXX
|
||||||
data += 32;
|
data += 32;
|
||||||
|
|
||||||
memmove(data, this->xDivs, numXDivs * sizeof(int32_t));
|
memcpy(data, xDivs, patch.numXDivs * sizeof(int32_t));
|
||||||
data += numXDivs * sizeof(int32_t);
|
data += patch.numXDivs * sizeof(int32_t);
|
||||||
memmove(data, this->yDivs, numYDivs * sizeof(int32_t));
|
memcpy(data, yDivs, patch.numYDivs * sizeof(int32_t));
|
||||||
data += numYDivs * sizeof(int32_t);
|
data += patch.numYDivs * sizeof(int32_t);
|
||||||
memmove(data, this->colors, numColors * sizeof(uint32_t));
|
memcpy(data, colors, patch.numColors * sizeof(uint32_t));
|
||||||
}
|
|
||||||
|
|
||||||
static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
|
fill9patchOffsets(reinterpret_cast<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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
|
static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
|
||||||
@ -312,14 +312,14 @@ static status_t getIdmapPackageId(const uint32_t* map, size_t mapSize, uint32_t
|
|||||||
return NO_ERROR;
|
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");
|
Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(inData);
|
||||||
return NULL;
|
patch->wasDeserialized = true;
|
||||||
}
|
fill9patchOffsets(patch);
|
||||||
deserializeInternal(inData, (Res_png_9patch*) inData);
|
|
||||||
return (Res_png_9patch*) inData;
|
return patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
@ -57,7 +57,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
|||||||
if (vertices) return vertices;
|
if (vertices) return vertices;
|
||||||
|
|
||||||
int8_t emptyQuads = 0;
|
int8_t emptyQuads = 0;
|
||||||
mColors = patch->colors;
|
mColors = patch->getColors();
|
||||||
|
|
||||||
const int8_t numColors = patch->numColors;
|
const int8_t numColors = patch->numColors;
|
||||||
if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
|
if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
|
||||||
@ -79,8 +79,8 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig
|
|||||||
TextureVertex* tempVertices = new TextureVertex[maxVertices];
|
TextureVertex* tempVertices = new TextureVertex[maxVertices];
|
||||||
TextureVertex* vertex = tempVertices;
|
TextureVertex* vertex = tempVertices;
|
||||||
|
|
||||||
const int32_t* xDivs = patch->xDivs;
|
const int32_t* xDivs = patch->getXDivs();
|
||||||
const int32_t* yDivs = patch->yDivs;
|
const int32_t* yDivs = patch->getYDivs();
|
||||||
|
|
||||||
const uint32_t xStretchCount = (xCount + 1) >> 1;
|
const uint32_t xStretchCount = (xCount + 1) >> 1;
|
||||||
const uint32_t yStretchCount = (yCount + 1) >> 1;
|
const uint32_t yStretchCount = (yCount + 1) >> 1;
|
||||||
|
@ -66,7 +66,7 @@ private:
|
|||||||
void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
|
void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
|
||||||
float u1, float v1, float u2, float v2, uint32_t& quadCount);
|
float u1, float v1, float u2, float v2, uint32_t& quadCount);
|
||||||
|
|
||||||
uint32_t* mColors;
|
const uint32_t* mColors;
|
||||||
UvMapper mUvMapper;
|
UvMapper mUvMapper;
|
||||||
}; // struct Patch
|
}; // struct Patch
|
||||||
|
|
||||||
|
@ -35,7 +35,9 @@ png_flush_aapt_file(png_structp png_ptr)
|
|||||||
// This holds an image as 8bpp RGBA.
|
// This holds an image as 8bpp RGBA.
|
||||||
struct image_info
|
struct image_info
|
||||||
{
|
{
|
||||||
image_info() : rows(NULL), is9Patch(false), allocRows(NULL) { }
|
image_info() : rows(NULL), is9Patch(false),
|
||||||
|
xDivs(NULL), yDivs(NULL), colors(NULL), allocRows(NULL) { }
|
||||||
|
|
||||||
~image_info() {
|
~image_info() {
|
||||||
if (rows && rows != allocRows) {
|
if (rows && rows != allocRows) {
|
||||||
free(rows);
|
free(rows);
|
||||||
@ -46,9 +48,15 @@ struct image_info
|
|||||||
}
|
}
|
||||||
free(allocRows);
|
free(allocRows);
|
||||||
}
|
}
|
||||||
free(info9Patch.xDivs);
|
free(xDivs);
|
||||||
free(info9Patch.yDivs);
|
free(yDivs);
|
||||||
free(info9Patch.colors);
|
free(colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* serialize9patch() {
|
||||||
|
void* serialized = Res_png_9patch::serialize(info9Patch, xDivs, yDivs, colors);
|
||||||
|
reinterpret_cast<Res_png_9patch*>(serialized)->deviceToFile();
|
||||||
|
return serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
png_uint_32 width;
|
png_uint_32 width;
|
||||||
@ -58,6 +66,9 @@ struct image_info
|
|||||||
// 9-patch info.
|
// 9-patch info.
|
||||||
bool is9Patch;
|
bool is9Patch;
|
||||||
Res_png_9patch info9Patch;
|
Res_png_9patch info9Patch;
|
||||||
|
int32_t* xDivs;
|
||||||
|
int32_t* yDivs;
|
||||||
|
uint32_t* colors;
|
||||||
|
|
||||||
// Layout padding, if relevant
|
// Layout padding, if relevant
|
||||||
bool haveLayoutBounds;
|
bool haveLayoutBounds;
|
||||||
@ -430,10 +441,10 @@ static uint32_t get_color(image_info* image, int hpatch, int vpatch)
|
|||||||
{
|
{
|
||||||
int left, right, top, bottom;
|
int left, right, top, bottom;
|
||||||
select_patch(
|
select_patch(
|
||||||
hpatch, image->info9Patch.xDivs[0], image->info9Patch.xDivs[1],
|
hpatch, image->xDivs[0], image->xDivs[1],
|
||||||
image->width, &left, &right);
|
image->width, &left, &right);
|
||||||
select_patch(
|
select_patch(
|
||||||
vpatch, image->info9Patch.yDivs[0], image->info9Patch.yDivs[1],
|
vpatch, image->yDivs[0], image->yDivs[1],
|
||||||
image->height, &top, &bottom);
|
image->height, &top, &bottom);
|
||||||
//printf("Selecting h=%d v=%d: (%d,%d)-(%d,%d)\n",
|
//printf("Selecting h=%d v=%d: (%d,%d)-(%d,%d)\n",
|
||||||
// hpatch, vpatch, left, top, right, bottom);
|
// hpatch, vpatch, left, top, right, bottom);
|
||||||
@ -452,8 +463,8 @@ static status_t do_9patch(const char* imageName, image_info* image)
|
|||||||
|
|
||||||
int maxSizeXDivs = W * sizeof(int32_t);
|
int maxSizeXDivs = W * sizeof(int32_t);
|
||||||
int maxSizeYDivs = H * sizeof(int32_t);
|
int maxSizeYDivs = H * sizeof(int32_t);
|
||||||
int32_t* xDivs = image->info9Patch.xDivs = (int32_t*) malloc(maxSizeXDivs);
|
int32_t* xDivs = image->xDivs = (int32_t*) malloc(maxSizeXDivs);
|
||||||
int32_t* yDivs = image->info9Patch.yDivs = (int32_t*) malloc(maxSizeYDivs);
|
int32_t* yDivs = image->yDivs = (int32_t*) malloc(maxSizeYDivs);
|
||||||
uint8_t numXDivs = 0;
|
uint8_t numXDivs = 0;
|
||||||
uint8_t numYDivs = 0;
|
uint8_t numYDivs = 0;
|
||||||
|
|
||||||
@ -609,7 +620,7 @@ static status_t do_9patch(const char* imageName, image_info* image)
|
|||||||
|
|
||||||
numColors = numRows * numCols;
|
numColors = numRows * numCols;
|
||||||
image->info9Patch.numColors = numColors;
|
image->info9Patch.numColors = numColors;
|
||||||
image->info9Patch.colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
|
image->colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
|
||||||
|
|
||||||
// Fill in color information for each patch.
|
// Fill in color information for each patch.
|
||||||
|
|
||||||
@ -652,7 +663,7 @@ static status_t do_9patch(const char* imageName, image_info* image)
|
|||||||
right = xDivs[i];
|
right = xDivs[i];
|
||||||
}
|
}
|
||||||
c = get_color(image->rows, left, top, right - 1, bottom - 1);
|
c = get_color(image->rows, left, top, right - 1, bottom - 1);
|
||||||
image->info9Patch.colors[colorIndex++] = c;
|
image->colors[colorIndex++] = c;
|
||||||
NOISY(if (c != Res_png_9patch::NO_COLOR) hasColor = true);
|
NOISY(if (c != Res_png_9patch::NO_COLOR) hasColor = true);
|
||||||
left = right;
|
left = right;
|
||||||
}
|
}
|
||||||
@ -664,14 +675,10 @@ static status_t do_9patch(const char* imageName, image_info* image)
|
|||||||
for (i=0; i<numColors; i++) {
|
for (i=0; i<numColors; i++) {
|
||||||
if (hasColor) {
|
if (hasColor) {
|
||||||
if (i == 0) printf("Colors in %s:\n ", imageName);
|
if (i == 0) printf("Colors in %s:\n ", imageName);
|
||||||
printf(" #%08x", image->info9Patch.colors[i]);
|
printf(" #%08x", image->colors[i]);
|
||||||
if (i == numColors - 1) printf("\n");
|
if (i == numColors - 1) printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image->is9Patch = true;
|
|
||||||
image->info9Patch.deviceToFile();
|
|
||||||
|
|
||||||
getout:
|
getout:
|
||||||
if (errorMsg) {
|
if (errorMsg) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -691,14 +698,10 @@ getout:
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkNinePatchSerialization(Res_png_9patch* inPatch, void * data)
|
static void checkNinePatchSerialization(Res_png_9patch* inPatch, void* data)
|
||||||
{
|
{
|
||||||
if (sizeof(void*) != sizeof(int32_t)) {
|
|
||||||
// can't deserialize on a non-32 bit system
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t patchSize = inPatch->serializedSize();
|
size_t patchSize = inPatch->serializedSize();
|
||||||
void * newData = malloc(patchSize);
|
void* newData = malloc(patchSize);
|
||||||
memcpy(newData, data, patchSize);
|
memcpy(newData, data, patchSize);
|
||||||
Res_png_9patch* outPatch = inPatch->deserialize(newData);
|
Res_png_9patch* outPatch = inPatch->deserialize(newData);
|
||||||
// deserialization is done in place, so outPatch == newData
|
// deserialization is done in place, so outPatch == newData
|
||||||
@ -721,34 +724,6 @@ static void checkNinePatchSerialization(Res_png_9patch* inPatch, void * data)
|
|||||||
free(newData);
|
free(newData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool patch_equals(Res_png_9patch& patch1, Res_png_9patch& patch2) {
|
|
||||||
if (!(patch1.numXDivs == patch2.numXDivs &&
|
|
||||||
patch1.numYDivs == patch2.numYDivs &&
|
|
||||||
patch1.numColors == patch2.numColors &&
|
|
||||||
patch1.paddingLeft == patch2.paddingLeft &&
|
|
||||||
patch1.paddingRight == patch2.paddingRight &&
|
|
||||||
patch1.paddingTop == patch2.paddingTop &&
|
|
||||||
patch1.paddingBottom == patch2.paddingBottom)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < patch1.numColors; i++) {
|
|
||||||
if (patch1.colors[i] != patch2.colors[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < patch1.numXDivs; i++) {
|
|
||||||
if (patch1.xDivs[i] != patch2.xDivs[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < patch1.numYDivs; i++) {
|
|
||||||
if (patch1.yDivs[i] != patch2.yDivs[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_image(int w, int h, png_bytepp rows, int color_type)
|
static void dump_image(int w, int h, png_bytepp rows, int color_type)
|
||||||
{
|
{
|
||||||
int i, j, rr, gg, bb, aa;
|
int i, j, rr, gg, bb, aa;
|
||||||
@ -1061,7 +1036,7 @@ static void write_png(const char* imageName,
|
|||||||
: (png_byte*)"npTc";
|
: (png_byte*)"npTc";
|
||||||
NOISY(printf("Adding 9-patch info...\n"));
|
NOISY(printf("Adding 9-patch info...\n"));
|
||||||
strcpy((char*)unknowns[p_index].name, "npTc");
|
strcpy((char*)unknowns[p_index].name, "npTc");
|
||||||
unknowns[p_index].data = (png_byte*)imageInfo.info9Patch.serialize();
|
unknowns[p_index].data = (png_byte*)imageInfo.serialize9patch();
|
||||||
unknowns[p_index].size = imageInfo.info9Patch.serializedSize();
|
unknowns[p_index].size = imageInfo.info9Patch.serializedSize();
|
||||||
// TODO: remove the check below when everything works
|
// TODO: remove the check below when everything works
|
||||||
checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data);
|
checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data);
|
||||||
|
Reference in New Issue
Block a user