Loading core/jni/android/graphics/BitmapFactory.cpp +9 −7 Original line number Diff line number Diff line Loading @@ -106,17 +106,19 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) { chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f); chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f); int32_t* xDivs = chunk->getXDivs(); for (int i = 0; i < chunk->numXDivs; i++) { chunk->xDivs[i] = int(chunk->xDivs[i] * scale + 0.5f); if (i > 0 && chunk->xDivs[i] == chunk->xDivs[i - 1]) { chunk->xDivs[i]++; xDivs[i] = int32_t(xDivs[i] * scale + 0.5f); if (i > 0 && xDivs[i] == xDivs[i - 1]) { xDivs[i]++; } } int32_t* yDivs = chunk->getXDivs(); for (int i = 0; i < chunk->numYDivs; i++) { chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f); if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) { chunk->yDivs[i]++; yDivs[i] = int32_t(yDivs[i] * scale + 0.5f); if (i > 0 && yDivs[i] == yDivs[i - 1]) { yDivs[i]++; } } } Loading Loading @@ -365,7 +367,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding return nullObjectReturn("primitive array == null"); } peeker.fPatch->serialize(array); memcpy(array, peeker.fPatch, peeker.fPatchSize); env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0); } Loading core/jni/android/graphics/NinePatchImpl.cpp +15 −12 Original line number Diff line number Diff line Loading @@ -116,12 +116,14 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, 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 // a mesh, which will be faster in most cases. if (false) { SkNinePatch::DrawMesh(canvas, bounds, bitmap, chunk.xDivs, chunk.numXDivs, chunk.yDivs, chunk.numYDivs, xDivs, chunk.numXDivs, yDivs, chunk.numYDivs, paint); return; } Loading @@ -145,8 +147,8 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, if (gTrace) { 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 xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]); ALOGV("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]); ALOGV("======== ninepatch xDivs [%d,%d]\n", xDivs[0], xDivs[1]); ALOGV("======== ninepatch yDivs [%d,%d]\n", yDivs[0], yDivs[1]); } #endif Loading @@ -171,8 +173,8 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, SkRect dst; SkIRect src; const int32_t x0 = chunk.xDivs[0]; const int32_t y0 = chunk.yDivs[0]; const int32_t x0 = xDivs[0]; const int32_t y0 = yDivs[0]; const SkColor initColor = ((SkPaint*)paint)->getColor(); const uint8_t numXDivs = chunk.numXDivs; const uint8_t numYDivs = chunk.numYDivs; Loading @@ -191,12 +193,12 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, int numStretchyXPixelsRemaining = 0; 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 numStretchyYPixelsRemaining = 0; 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; Loading Loading @@ -235,7 +237,7 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, src.fBottom = bitmapHeight; dst.fBottom = bounds.fBottom; } else { src.fBottom = chunk.yDivs[j]; src.fBottom = yDivs[j]; const int srcYSize = src.fBottom - src.fTop; if (yIsStretchable) { dst.fBottom = dst.fTop + calculateStretch(bounds.fBottom, dst.fTop, Loading @@ -252,15 +254,16 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, xIsStretchable = initialXIsStretchable; // The initial xDiv and whether the first column is considered // stretchable or not depends on whether xDiv[0] was zero or not. const uint32_t* colors = chunk.getColors(); for (i = xIsStretchable ? 1 : 0; i <= numXDivs && src.fLeft < bitmapWidth; i++, xIsStretchable = !xIsStretchable) { color = chunk.colors[colorIndex++]; color = colors[colorIndex++]; if (i == numXDivs) { src.fRight = bitmapWidth; dst.fRight = bounds.fRight; } else { src.fRight = chunk.xDivs[i]; src.fRight = xDivs[i]; if (dstRightsHaveBeenCached) { dst.fRight = dstRights[i]; } else { Loading core/jni/android/graphics/NinePatchPeeker.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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 Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize); memcpy(patchNew, patch, patchSize); // this relies on deserialization being done in place Res_png_9patch::deserialize(patchNew); patchNew->fileToDevice(); free(fPatch); fPatch = patchNew; fPatchSize = patchSize; //printf("9patch: (%d,%d)-(%d,%d)\n", // fPatch.sizeLeft, fPatch.sizeTop, // fPatch.sizeRight, fPatch.sizeBottom); Loading core/jni/android/graphics/NinePatchPeeker.h +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ public: // the host lives longer than we do, so a raw ptr is safe fHost = host; fPatch = NULL; fPatchSize = 0; fLayoutBounds = NULL; } Loading @@ -38,6 +39,7 @@ public: } Res_png_9patch* fPatch; size_t fPatchSize; int *fLayoutBounds; virtual bool peek(const char tag[], const void* data, size_t length); Loading include/androidfw/ResourceTypes.h +44 −25 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ namespace android { * two stretchable slices is exactly the ratio of their corresponding * 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 * starting and ending points of the first stretchable segment in that * axis. The next pair specifies the next stretchable segment, etc. So Loading @@ -92,32 +92,31 @@ namespace android { * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at * xDiv[2]. * * The array pointed to by the colors field lists contains hints for * each of the regions. They are ordered according left-to-right and * top-to-bottom as indicated above. For each segment that is a solid * color the array entry will contain that color value; otherwise it * will contain NO_COLOR. Segments that are completely transparent * will always have the value TRANSPARENT_COLOR. * The colors array contains hints for each of the regions. They are * ordered according left-to-right and top-to-bottom as indicated above. * For each segment that is a solid color the array entry will contain * that color value; otherwise it will contain NO_COLOR. Segments that * are completely transparent will always have the value TRANSPARENT_COLOR. * * The PNG chunk type is "npTc". */ struct Res_png_9patch { Res_png_9patch() : wasDeserialized(false), xDivs(NULL), yDivs(NULL), colors(NULL) { } Res_png_9patch() : wasDeserialized(false), xDivsOffset(0), yDivsOffset(0), colorsOffset(0) { } int8_t wasDeserialized; int8_t numXDivs; int8_t numYDivs; int8_t numColors; // 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. // Note: allocation/free of these pointers is left to the caller. int32_t* xDivs; int32_t* yDivs; // The offset (from the start of this structure) to the xDivs & yDivs // array for this 9patch. To get a pointer to this array, call // getXDivs or getYDivs. Note that the serialized form for 9patches places // the xDivs, yDivs and colors arrays immediately after the location // of the Res_png_9patch struct. uint32_t xDivsOffset; uint32_t yDivsOffset; int32_t paddingLeft, paddingRight; int32_t paddingTop, paddingBottom; Loading @@ -129,22 +128,42 @@ struct Res_png_9patch // The 9 patch segment is completely transparent. 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. void deviceToFile(); // Convert data from PNG file representation to device representation. void fileToDevice(); // Serialize/Marshall the patch data into a newly malloc-ed block void* serialize(); // Serialize/Marshall the patch data void serialize(void* outData); // Serialize/Marshall the patch data into a newly malloc-ed block. static void* serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs, 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 static Res_png_9patch* deserialize(const void* data); static Res_png_9patch* deserialize(void* data); // 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 Loading Loading
core/jni/android/graphics/BitmapFactory.cpp +9 −7 Original line number Diff line number Diff line Loading @@ -106,17 +106,19 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) { chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f); chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f); int32_t* xDivs = chunk->getXDivs(); for (int i = 0; i < chunk->numXDivs; i++) { chunk->xDivs[i] = int(chunk->xDivs[i] * scale + 0.5f); if (i > 0 && chunk->xDivs[i] == chunk->xDivs[i - 1]) { chunk->xDivs[i]++; xDivs[i] = int32_t(xDivs[i] * scale + 0.5f); if (i > 0 && xDivs[i] == xDivs[i - 1]) { xDivs[i]++; } } int32_t* yDivs = chunk->getXDivs(); for (int i = 0; i < chunk->numYDivs; i++) { chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f); if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) { chunk->yDivs[i]++; yDivs[i] = int32_t(yDivs[i] * scale + 0.5f); if (i > 0 && yDivs[i] == yDivs[i - 1]) { yDivs[i]++; } } } Loading Loading @@ -365,7 +367,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding return nullObjectReturn("primitive array == null"); } peeker.fPatch->serialize(array); memcpy(array, peeker.fPatch, peeker.fPatchSize); env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0); } Loading
core/jni/android/graphics/NinePatchImpl.cpp +15 −12 Original line number Diff line number Diff line Loading @@ -116,12 +116,14 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, 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 // a mesh, which will be faster in most cases. if (false) { SkNinePatch::DrawMesh(canvas, bounds, bitmap, chunk.xDivs, chunk.numXDivs, chunk.yDivs, chunk.numYDivs, xDivs, chunk.numXDivs, yDivs, chunk.numYDivs, paint); return; } Loading @@ -145,8 +147,8 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, if (gTrace) { 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 xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]); ALOGV("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]); ALOGV("======== ninepatch xDivs [%d,%d]\n", xDivs[0], xDivs[1]); ALOGV("======== ninepatch yDivs [%d,%d]\n", yDivs[0], yDivs[1]); } #endif Loading @@ -171,8 +173,8 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, SkRect dst; SkIRect src; const int32_t x0 = chunk.xDivs[0]; const int32_t y0 = chunk.yDivs[0]; const int32_t x0 = xDivs[0]; const int32_t y0 = yDivs[0]; const SkColor initColor = ((SkPaint*)paint)->getColor(); const uint8_t numXDivs = chunk.numXDivs; const uint8_t numYDivs = chunk.numYDivs; Loading @@ -191,12 +193,12 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, int numStretchyXPixelsRemaining = 0; 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 numStretchyYPixelsRemaining = 0; 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; Loading Loading @@ -235,7 +237,7 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, src.fBottom = bitmapHeight; dst.fBottom = bounds.fBottom; } else { src.fBottom = chunk.yDivs[j]; src.fBottom = yDivs[j]; const int srcYSize = src.fBottom - src.fTop; if (yIsStretchable) { dst.fBottom = dst.fTop + calculateStretch(bounds.fBottom, dst.fTop, Loading @@ -252,15 +254,16 @@ void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, xIsStretchable = initialXIsStretchable; // The initial xDiv and whether the first column is considered // stretchable or not depends on whether xDiv[0] was zero or not. const uint32_t* colors = chunk.getColors(); for (i = xIsStretchable ? 1 : 0; i <= numXDivs && src.fLeft < bitmapWidth; i++, xIsStretchable = !xIsStretchable) { color = chunk.colors[colorIndex++]; color = colors[colorIndex++]; if (i == numXDivs) { src.fRight = bitmapWidth; dst.fRight = bounds.fRight; } else { src.fRight = chunk.xDivs[i]; src.fRight = xDivs[i]; if (dstRightsHaveBeenCached) { dst.fRight = dstRights[i]; } else { Loading
core/jni/android/graphics/NinePatchPeeker.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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 Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize); memcpy(patchNew, patch, patchSize); // this relies on deserialization being done in place Res_png_9patch::deserialize(patchNew); patchNew->fileToDevice(); free(fPatch); fPatch = patchNew; fPatchSize = patchSize; //printf("9patch: (%d,%d)-(%d,%d)\n", // fPatch.sizeLeft, fPatch.sizeTop, // fPatch.sizeRight, fPatch.sizeBottom); Loading
core/jni/android/graphics/NinePatchPeeker.h +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ public: // the host lives longer than we do, so a raw ptr is safe fHost = host; fPatch = NULL; fPatchSize = 0; fLayoutBounds = NULL; } Loading @@ -38,6 +39,7 @@ public: } Res_png_9patch* fPatch; size_t fPatchSize; int *fLayoutBounds; virtual bool peek(const char tag[], const void* data, size_t length); Loading
include/androidfw/ResourceTypes.h +44 −25 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ namespace android { * two stretchable slices is exactly the ratio of their corresponding * 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 * starting and ending points of the first stretchable segment in that * axis. The next pair specifies the next stretchable segment, etc. So Loading @@ -92,32 +92,31 @@ namespace android { * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at * xDiv[2]. * * The array pointed to by the colors field lists contains hints for * each of the regions. They are ordered according left-to-right and * top-to-bottom as indicated above. For each segment that is a solid * color the array entry will contain that color value; otherwise it * will contain NO_COLOR. Segments that are completely transparent * will always have the value TRANSPARENT_COLOR. * The colors array contains hints for each of the regions. They are * ordered according left-to-right and top-to-bottom as indicated above. * For each segment that is a solid color the array entry will contain * that color value; otherwise it will contain NO_COLOR. Segments that * are completely transparent will always have the value TRANSPARENT_COLOR. * * The PNG chunk type is "npTc". */ struct Res_png_9patch { Res_png_9patch() : wasDeserialized(false), xDivs(NULL), yDivs(NULL), colors(NULL) { } Res_png_9patch() : wasDeserialized(false), xDivsOffset(0), yDivsOffset(0), colorsOffset(0) { } int8_t wasDeserialized; int8_t numXDivs; int8_t numYDivs; int8_t numColors; // 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. // Note: allocation/free of these pointers is left to the caller. int32_t* xDivs; int32_t* yDivs; // The offset (from the start of this structure) to the xDivs & yDivs // array for this 9patch. To get a pointer to this array, call // getXDivs or getYDivs. Note that the serialized form for 9patches places // the xDivs, yDivs and colors arrays immediately after the location // of the Res_png_9patch struct. uint32_t xDivsOffset; uint32_t yDivsOffset; int32_t paddingLeft, paddingRight; int32_t paddingTop, paddingBottom; Loading @@ -129,22 +128,42 @@ struct Res_png_9patch // The 9 patch segment is completely transparent. 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. void deviceToFile(); // Convert data from PNG file representation to device representation. void fileToDevice(); // Serialize/Marshall the patch data into a newly malloc-ed block void* serialize(); // Serialize/Marshall the patch data void serialize(void* outData); // Serialize/Marshall the patch data into a newly malloc-ed block. static void* serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs, 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 static Res_png_9patch* deserialize(const void* data); static Res_png_9patch* deserialize(void* data); // 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 Loading