Skip to content

Commit 1da8f00

Browse files
Amith YamasaniAndroid (Google) Code Review
authored andcommitted
Merge "Embed layout padding in nine patch images"
2 parents 5b86de1 + ec4a504 commit 1da8f00

File tree

13 files changed

+273
-52
lines changed

13 files changed

+273
-52
lines changed

core/jni/android/graphics/Bitmap.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
236236
0, 0, width, height, bitmap);
237237
}
238238

239-
return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL);
239+
return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);
240240
}
241241

242242
static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
@@ -248,7 +248,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
248248
return NULL;
249249
}
250250

251-
return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL);
251+
return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL, NULL);
252252
}
253253

254254
static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
@@ -407,7 +407,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
407407
bitmap->unlockPixels();
408408

409409
blob.release();
410-
return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density);
410+
return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, NULL, density);
411411
}
412412

413413
static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
@@ -485,7 +485,7 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
485485
env->ReleaseIntArrayElements(offsetXY, array, 0);
486486
}
487487

488-
return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL);
488+
return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL, NULL);
489489
}
490490

491491
///////////////////////////////////////////////////////////////////////////////

core/jni/android/graphics/BitmapFactory.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jfieldID gOptions_mimeFieldID;
3535
jfieldID gOptions_mCancelID;
3636
jfieldID gOptions_bitmapFieldID;
3737
jfieldID gBitmap_nativeBitmapFieldID;
38+
jfieldID gBitmap_layoutBoundsFieldID;
3839

3940
#if 0
4041
#define TRACE_BITMAP(code) code
@@ -276,7 +277,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
276277
}
277278

278279
jbyteArray ninePatchChunk = NULL;
279-
if (peeker.fPatchIsValid) {
280+
if (peeker.fPatch != NULL) {
280281
if (willScale) {
281282
scaleNinePatchChunk(peeker.fPatch, scale);
282283
}
@@ -296,6 +297,18 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
296297
env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
297298
}
298299

300+
jintArray layoutBounds = NULL;
301+
if (peeker.fLayoutBounds != NULL) {
302+
layoutBounds = env->NewIntArray(4);
303+
if (layoutBounds == NULL) {
304+
return nullObjectReturn("layoutBounds == null");
305+
}
306+
307+
env->SetIntArrayRegion(layoutBounds, 0, 4, (jint*) peeker.fLayoutBounds);
308+
if (javaBitmap != NULL) {
309+
env->SetObjectField(javaBitmap, gBitmap_layoutBoundsFieldID, layoutBounds);
310+
}
311+
}
299312
// detach bitmap from its autodeleter, since we want to own it now
300313
adb.detach();
301314

@@ -321,7 +334,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
321334
}
322335

323336
if (padding) {
324-
if (peeker.fPatchIsValid) {
337+
if (peeker.fPatch != NULL) {
325338
GraphicsJNI::set_jrect(env, padding,
326339
peeker.fPatch->paddingLeft, peeker.fPatch->paddingTop,
327340
peeker.fPatch->paddingRight, peeker.fPatch->paddingBottom);
@@ -350,7 +363,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
350363
}
351364
// now create the java bitmap
352365
return GraphicsJNI::createBitmap(env, bitmap, javaAllocator.getStorageObj(),
353-
isMutable, ninePatchChunk);
366+
isMutable, ninePatchChunk, layoutBounds, -1);
354367
}
355368

356369
static jobject nativeDecodeStreamScaled(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
@@ -576,7 +589,7 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
576589
jclass bitmap_class = env->FindClass("android/graphics/Bitmap");
577590
SkASSERT(bitmap_class);
578591
gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, bitmap_class, "mNativeBitmap", "I");
579-
592+
gBitmap_layoutBoundsFieldID = getFieldIDCheck(env, bitmap_class, "mLayoutBounds", "[I");
580593
int ret = AndroidRuntime::registerNativeMethods(env,
581594
"android/graphics/BitmapFactory$Options",
582595
gOptionsMethods,

core/jni/android/graphics/BitmapRegionDecoder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *b
244244

245245
JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator();
246246
jbyteArray buff = allocator->getStorageObjAndReset();
247-
return GraphicsJNI::createBitmap(env, bitmap, buff, false, NULL, -1);
247+
return GraphicsJNI::createBitmap(env, bitmap, buff, false, NULL, NULL, -1);
248248
}
249249

250250
static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {

core/jni/android/graphics/Graphics.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,22 +345,22 @@ SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
345345
///////////////////////////////////////////////////////////////////////////////////////////
346346

347347
jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
348-
bool isMutable, jbyteArray ninepatch, int density)
348+
bool isMutable, jbyteArray ninepatch, jintArray layoutbounds,
349+
int density)
349350
{
350351
SkASSERT(bitmap);
351352
SkASSERT(bitmap->pixelRef());
352-
353353
jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
354354
static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)),
355-
buffer, isMutable, ninepatch, density);
355+
buffer, isMutable, ninepatch, layoutbounds, density);
356356
hasException(env); // For the side effect of logging.
357357
return obj;
358358
}
359359

360360
jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
361361
jbyteArray ninepatch, int density)
362362
{
363-
return createBitmap(env, bitmap, NULL, isMutable, ninepatch, density);
363+
return createBitmap(env, bitmap, NULL, isMutable, ninepatch, NULL, density);
364364
}
365365

366366

@@ -587,7 +587,7 @@ int register_android_graphics_Graphics(JNIEnv* env)
587587
gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
588588
gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
589589
gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
590-
"(I[BZ[BI)V");
590+
"(I[BZ[B[II)V");
591591
gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
592592
gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V");
593593

core/jni/android/graphics/GraphicsJNI.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class GraphicsJNI {
5353
storage array (may be null).
5454
*/
5555
static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
56-
bool isMutable, jbyteArray ninepatch, int density = -1);
56+
bool isMutable, jbyteArray ninepatch, jintArray layoutbounds,
57+
int density = -1);
5758

5859
static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
5960
jbyteArray ninepatch, int density = -1);

core/jni/android/graphics/NinePatchPeeker.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,11 @@ bool NinePatchPeeker::peek(const char tag[], const void* data, size_t length) {
3131
// this relies on deserialization being done in place
3232
Res_png_9patch::deserialize(patchNew);
3333
patchNew->fileToDevice();
34-
if (fPatchIsValid) {
35-
free(fPatch);
36-
}
34+
free(fPatch);
3735
fPatch = patchNew;
3836
//printf("9patch: (%d,%d)-(%d,%d)\n",
3937
// fPatch.sizeLeft, fPatch.sizeTop,
4038
// fPatch.sizeRight, fPatch.sizeBottom);
41-
fPatchIsValid = true;
4239

4340
// now update our host to force index or 32bit config
4441
// 'cause we don't want 565 predithered, since as a 9patch, we know
@@ -52,8 +49,9 @@ bool NinePatchPeeker::peek(const char tag[], const void* data, size_t length) {
5249
SkBitmap::kARGB_8888_Config,
5350
};
5451
fHost->setPrefConfigTable(gNo565Pref);
55-
} else {
56-
fPatch = NULL;
52+
} else if (strcmp("npLb", tag) == 0 && length == sizeof(int) * 4) {
53+
fLayoutBounds = new int[4];
54+
memcpy(fLayoutBounds, data, sizeof(int) * 4);
5755
}
5856
return true; // keep on decoding
5957
}

core/jni/android/graphics/NinePatchPeeker.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ class NinePatchPeeker : public SkImageDecoder::Peeker {
2828
NinePatchPeeker(SkImageDecoder* host) {
2929
// the host lives longer than we do, so a raw ptr is safe
3030
fHost = host;
31-
fPatchIsValid = false;
31+
fPatch = NULL;
32+
fLayoutBounds = NULL;
3233
}
3334

3435
~NinePatchPeeker() {
35-
if (fPatchIsValid) {
36-
free(fPatch);
37-
}
36+
free(fPatch);
37+
delete fLayoutBounds;
3838
}
3939

40-
bool fPatchIsValid;
4140
Res_png_9patch* fPatch;
41+
int *fLayoutBounds;
4242

4343
virtual bool peek(const char tag[], const void* data, size_t length);
4444
};

graphics/java/android/graphics/Bitmap.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616

1717
package android.graphics;
1818

19+
import android.os.Debug;
1920
import android.os.Parcel;
2021
import android.os.Parcelable;
2122
import android.util.DisplayMetrics;
23+
import android.util.Log;
24+
2225
import java.io.OutputStream;
2326
import java.nio.Buffer;
2427
import java.nio.ByteBuffer;
@@ -57,6 +60,7 @@ public final class Bitmap implements Parcelable {
5760

5861
private final boolean mIsMutable;
5962
private byte[] mNinePatchChunk; // may be null
63+
private int[] mLayoutBounds; // may be null
6064
private int mWidth = -1;
6165
private int mHeight = -1;
6266
private boolean mRecycled;
@@ -95,6 +99,19 @@ bitmap int (pointer).
9599
*/
96100
/*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
97101
int density) {
102+
this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
103+
}
104+
105+
/**
106+
* @noinspection UnusedDeclaration
107+
*/
108+
/* Private constructor that must received an already allocated native
109+
bitmap int (pointer).
110+
111+
This can be called from JNI code.
112+
*/
113+
/*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
114+
int[] layoutBounds, int density) {
98115
if (nativeBitmap == 0) {
99116
throw new RuntimeException("internal error: native bitmap is 0");
100117
}
@@ -106,6 +123,7 @@ bitmap int (pointer).
106123

107124
mIsMutable = isMutable;
108125
mNinePatchChunk = ninePatchChunk;
126+
mLayoutBounds = layoutBounds;
109127
if (density >= 0) {
110128
mDensity = density;
111129
}
@@ -163,6 +181,16 @@ public void setNinePatchChunk(byte[] chunk) {
163181
mNinePatchChunk = chunk;
164182
}
165183

184+
/**
185+
* Sets the layout bounds as an array of left, top, right, bottom integers
186+
* @param padding the array containing the padding values
187+
*
188+
* @hide
189+
*/
190+
public void setLayoutBounds(int[] bounds) {
191+
mLayoutBounds = bounds;
192+
}
193+
166194
/**
167195
* Free the native object associated with this bitmap, and clear the
168196
* reference to the pixel data. This will not free the pixel data synchronously;
@@ -689,6 +717,14 @@ public byte[] getNinePatchChunk() {
689717
return mNinePatchChunk;
690718
}
691719

720+
/**
721+
* @hide
722+
* @return the layout padding [left, right, top, bottom]
723+
*/
724+
public int[] getLayoutBounds() {
725+
return mLayoutBounds;
726+
}
727+
692728
/**
693729
* Specifies the known formats a bitmap can be compressed into
694730
*/

graphics/java/android/graphics/BitmapFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ public static Bitmap decodeByteArray(byte[] data, int offset, int length, Option
424424
throw new ArrayIndexOutOfBoundsException();
425425
}
426426
Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
427+
427428
if (bm == null && opts != null && opts.inBitmap != null) {
428429
throw new IllegalArgumentException("Problem decoding into existing bitmap");
429430
}
@@ -554,7 +555,6 @@ private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {
554555
if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
555556
return bm;
556557
}
557-
558558
byte[] np = bm.getNinePatchChunk();
559559
final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
560560
if (opts.inScaled || isNinePatch) {

graphics/java/android/graphics/drawable/Drawable.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,13 @@ public static Drawable createFromResourceStream(Resources res, TypedValue value,
773773
np = null;
774774
pad = null;
775775
}
776-
return drawableFromBitmap(res, bm, np, pad, srcName);
776+
int[] layoutBounds = bm.getLayoutBounds();
777+
Rect layoutBoundsRect = null;
778+
if (layoutBounds != null) {
779+
layoutBoundsRect = new Rect(layoutBounds[0], layoutBounds[1],
780+
layoutBounds[2], layoutBounds[3]);
781+
}
782+
return drawableFromBitmap(res, bm, np, pad, layoutBoundsRect, srcName);
777783
}
778784
return null;
779785
}
@@ -875,7 +881,7 @@ public static Drawable createFromPath(String pathName) {
875881

876882
Bitmap bm = BitmapFactory.decodeFile(pathName);
877883
if (bm != null) {
878-
return drawableFromBitmap(null, bm, null, null, pathName);
884+
return drawableFromBitmap(null, bm, null, null, null, pathName);
879885
}
880886

881887
return null;
@@ -956,10 +962,12 @@ public ConstantState getConstantState() {
956962
}
957963

958964
private static Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np,
959-
Rect pad, String srcName) {
965+
Rect pad, Rect layoutBounds, String srcName) {
960966

961967
if (np != null) {
962-
return new NinePatchDrawable(res, bm, np, pad, srcName);
968+
NinePatchDrawable npd = new NinePatchDrawable(res, bm, np, pad, srcName);
969+
npd.setLayoutBounds(layoutBounds);
970+
return npd;
963971
}
964972

965973
return new BitmapDrawable(res, bm);

0 commit comments

Comments
 (0)