Loading core/java/android/view/PointerIcon.java +36 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.Bitmap; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Parcel; Loading Loading @@ -142,6 +143,10 @@ public final class PointerIcon implements Parcelable { private Bitmap mBitmap; private float mHotSpotX; private float mHotSpotY; // The bitmaps for the additional frame of animated pointer icon. Note that the first frame // will be stored in mBitmap. private Bitmap mBitmapFrames[]; private int mDurationPerFrame; private PointerIcon(int style) { mStyle = style; Loading Loading @@ -472,6 +477,36 @@ public final class PointerIcon implements Parcelable { } else { drawable = context.getDrawable(bitmapRes); } if (drawable instanceof AnimationDrawable) { // Extract animation frame bitmaps. final AnimationDrawable animationDrawable = (AnimationDrawable) drawable; final int frames = animationDrawable.getNumberOfFrames(); drawable = animationDrawable.getFrame(0); if (frames == 1) { Log.w(TAG, "Animation icon with single frame -- simply treating the first " + "frame as a normal bitmap icon."); } else { // Assumes they have the exact duration. mDurationPerFrame = animationDrawable.getDuration(0); mBitmapFrames = new Bitmap[frames - 1]; final int width = drawable.getIntrinsicWidth(); final int height = drawable.getIntrinsicHeight(); for (int i = 1; i < frames; ++i) { Drawable drawableFrame = animationDrawable.getFrame(i); if (!(drawableFrame instanceof BitmapDrawable)) { throw new IllegalArgumentException("Frame of an animated pointer icon " + "must refer to a bitmap drawable."); } if (drawableFrame.getIntrinsicWidth() != width || drawableFrame.getIntrinsicHeight() != height) { throw new IllegalArgumentException("The bitmap size of " + i + "-th frame " + "is different. All frames should have the exact same size and " + "share the same hotspot."); } mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap(); } } } if (!(drawable instanceof BitmapDrawable)) { throw new IllegalArgumentException("<pointer-icon> bitmap attribute must " + "refer to a bitmap drawable."); Loading Loading @@ -509,8 +544,7 @@ public final class PointerIcon implements Parcelable { case STYLE_HELP: return com.android.internal.R.styleable.Pointer_pointerIconHelp; case STYLE_WAIT: // falls back to the default icon because no animation support. return com.android.internal.R.styleable.Pointer_pointerIconArrow; return com.android.internal.R.styleable.Pointer_pointerIconWait; case STYLE_CELL: return com.android.internal.R.styleable.Pointer_pointerIconCell; case STYLE_CROSSHAIR: Loading core/jni/android_view_PointerIcon.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <android_runtime/Log.h> #include <utils/Log.h> #include <android/graphics/GraphicsJNI.h> #include "ScopedLocalRef.h" #include "core_jni_helpers.h" Loading @@ -35,6 +36,8 @@ static struct { jfieldID mBitmap; jfieldID mHotSpotX; jfieldID mHotSpotY; jfieldID mBitmapFrames; jfieldID mDurationPerFrame; jmethodID getSystemIcon; jmethodID load; } gPointerIconClassInfo; Loading Loading @@ -84,6 +87,19 @@ status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobj env->DeleteLocalRef(bitmapObj); } ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>( env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmapFrames))); if (bitmapFramesObj.get()) { outPointerIcon->durationPerFrame = env->GetIntField( loadedPointerIconObj, gPointerIconClassInfo.mDurationPerFrame); jsize size = env->GetArrayLength(bitmapFramesObj.get()); outPointerIcon->bitmapFrames.resize(size); for (jsize i = 0; i < size; ++i) { ScopedLocalRef<jobject> bitmapObj(env, env->GetObjectArrayElement(bitmapFramesObj.get(), i)); GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmapFrames[i])); } } env->DeleteLocalRef(loadedPointerIconObj); return OK; } Loading Loading @@ -121,6 +137,12 @@ int register_android_view_PointerIcon(JNIEnv* env) { gPointerIconClassInfo.mHotSpotY = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mHotSpotY", "F"); gPointerIconClassInfo.mBitmapFrames = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mBitmapFrames", "[Landroid/graphics/Bitmap;"); gPointerIconClassInfo.mDurationPerFrame = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mDurationPerFrame", "I"); gPointerIconClassInfo.getSystemIcon = GetStaticMethodIDOrDie(env, gPointerIconClassInfo.clazz, "getSystemIcon", "(Landroid/content/Context;I)Landroid/view/PointerIcon;"); Loading core/jni/android_view_PointerIcon.h +6 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include "jni.h" #include <vector> #include <utils/Errors.h> #include <SkBitmap.h> Loading Loading @@ -69,6 +71,8 @@ struct PointerIcon { SkBitmap bitmap; float hotSpotX; float hotSpotY; std::vector<SkBitmap> bitmapFrames; int32_t durationPerFrame; inline bool isNullIcon() { return style == POINTER_ICON_STYLE_NULL; Loading @@ -79,6 +83,8 @@ struct PointerIcon { bitmap.reset(); hotSpotX = 0; hotSpotY = 0; bitmapFrames.clear(); durationPerFrame = 0; } }; Loading core/res/res/drawable-mdpi/pointer_wait_0.png 0 → 100644 +606 B Loading image diff... core/res/res/drawable-mdpi/pointer_wait_1.png 0 → 100644 +603 B Loading image diff... Loading
core/java/android/view/PointerIcon.java +36 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.Bitmap; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Parcel; Loading Loading @@ -142,6 +143,10 @@ public final class PointerIcon implements Parcelable { private Bitmap mBitmap; private float mHotSpotX; private float mHotSpotY; // The bitmaps for the additional frame of animated pointer icon. Note that the first frame // will be stored in mBitmap. private Bitmap mBitmapFrames[]; private int mDurationPerFrame; private PointerIcon(int style) { mStyle = style; Loading Loading @@ -472,6 +477,36 @@ public final class PointerIcon implements Parcelable { } else { drawable = context.getDrawable(bitmapRes); } if (drawable instanceof AnimationDrawable) { // Extract animation frame bitmaps. final AnimationDrawable animationDrawable = (AnimationDrawable) drawable; final int frames = animationDrawable.getNumberOfFrames(); drawable = animationDrawable.getFrame(0); if (frames == 1) { Log.w(TAG, "Animation icon with single frame -- simply treating the first " + "frame as a normal bitmap icon."); } else { // Assumes they have the exact duration. mDurationPerFrame = animationDrawable.getDuration(0); mBitmapFrames = new Bitmap[frames - 1]; final int width = drawable.getIntrinsicWidth(); final int height = drawable.getIntrinsicHeight(); for (int i = 1; i < frames; ++i) { Drawable drawableFrame = animationDrawable.getFrame(i); if (!(drawableFrame instanceof BitmapDrawable)) { throw new IllegalArgumentException("Frame of an animated pointer icon " + "must refer to a bitmap drawable."); } if (drawableFrame.getIntrinsicWidth() != width || drawableFrame.getIntrinsicHeight() != height) { throw new IllegalArgumentException("The bitmap size of " + i + "-th frame " + "is different. All frames should have the exact same size and " + "share the same hotspot."); } mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap(); } } } if (!(drawable instanceof BitmapDrawable)) { throw new IllegalArgumentException("<pointer-icon> bitmap attribute must " + "refer to a bitmap drawable."); Loading Loading @@ -509,8 +544,7 @@ public final class PointerIcon implements Parcelable { case STYLE_HELP: return com.android.internal.R.styleable.Pointer_pointerIconHelp; case STYLE_WAIT: // falls back to the default icon because no animation support. return com.android.internal.R.styleable.Pointer_pointerIconArrow; return com.android.internal.R.styleable.Pointer_pointerIconWait; case STYLE_CELL: return com.android.internal.R.styleable.Pointer_pointerIconCell; case STYLE_CROSSHAIR: Loading
core/jni/android_view_PointerIcon.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <android_runtime/Log.h> #include <utils/Log.h> #include <android/graphics/GraphicsJNI.h> #include "ScopedLocalRef.h" #include "core_jni_helpers.h" Loading @@ -35,6 +36,8 @@ static struct { jfieldID mBitmap; jfieldID mHotSpotX; jfieldID mHotSpotY; jfieldID mBitmapFrames; jfieldID mDurationPerFrame; jmethodID getSystemIcon; jmethodID load; } gPointerIconClassInfo; Loading Loading @@ -84,6 +87,19 @@ status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobj env->DeleteLocalRef(bitmapObj); } ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>( env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmapFrames))); if (bitmapFramesObj.get()) { outPointerIcon->durationPerFrame = env->GetIntField( loadedPointerIconObj, gPointerIconClassInfo.mDurationPerFrame); jsize size = env->GetArrayLength(bitmapFramesObj.get()); outPointerIcon->bitmapFrames.resize(size); for (jsize i = 0; i < size; ++i) { ScopedLocalRef<jobject> bitmapObj(env, env->GetObjectArrayElement(bitmapFramesObj.get(), i)); GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmapFrames[i])); } } env->DeleteLocalRef(loadedPointerIconObj); return OK; } Loading Loading @@ -121,6 +137,12 @@ int register_android_view_PointerIcon(JNIEnv* env) { gPointerIconClassInfo.mHotSpotY = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mHotSpotY", "F"); gPointerIconClassInfo.mBitmapFrames = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mBitmapFrames", "[Landroid/graphics/Bitmap;"); gPointerIconClassInfo.mDurationPerFrame = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mDurationPerFrame", "I"); gPointerIconClassInfo.getSystemIcon = GetStaticMethodIDOrDie(env, gPointerIconClassInfo.clazz, "getSystemIcon", "(Landroid/content/Context;I)Landroid/view/PointerIcon;"); Loading
core/jni/android_view_PointerIcon.h +6 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include "jni.h" #include <vector> #include <utils/Errors.h> #include <SkBitmap.h> Loading Loading @@ -69,6 +71,8 @@ struct PointerIcon { SkBitmap bitmap; float hotSpotX; float hotSpotY; std::vector<SkBitmap> bitmapFrames; int32_t durationPerFrame; inline bool isNullIcon() { return style == POINTER_ICON_STYLE_NULL; Loading @@ -79,6 +83,8 @@ struct PointerIcon { bitmap.reset(); hotSpotX = 0; hotSpotY = 0; bitmapFrames.clear(); durationPerFrame = 0; } }; Loading