diff --git a/meson.build b/meson.build index b8e1b7bb..876325a7 100644 --- a/meson.build +++ b/meson.build @@ -80,6 +80,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/database/android_database_SQLiteCommon.c', 'src/api-impl-jni/database/android_database_SQLiteConnection.c', 'src/api-impl-jni/graphics/android_graphics_BitmapFactory.c', + 'src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c', 'src/api-impl-jni/graphics/android_graphics_Typeface.c', 'src/api-impl-jni/media/android_media_MediaCodec.c', 'src/api-impl-jni/android_content_res_AssetManager.c', diff --git a/src/api-impl-jni/generated_headers/android_graphics_drawable_Drawable.h b/src/api-impl-jni/generated_headers/android_graphics_drawable_Drawable.h new file mode 100644 index 00000000..57c39e84 --- /dev/null +++ b/src/api-impl-jni/generated_headers/android_graphics_drawable_Drawable.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class android_graphics_drawable_Drawable */ + +#ifndef _Included_android_graphics_drawable_Drawable +#define _Included_android_graphics_drawable_Drawable +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: android_graphics_drawable_Drawable + * Method: native_paintable_from_path + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1paintable_1from_1path + (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/api-impl-jni/generated_headers/android_view_View.h b/src/api-impl-jni/generated_headers/android_view_View.h index e4bec433..093386a2 100644 --- a/src/api-impl-jni/generated_headers/android_view_View.h +++ b/src/api-impl-jni/generated_headers/android_view_View.h @@ -279,6 +279,14 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1layout JNIEXPORT void JNICALL Java_android_view_View_native_1requestLayout (JNIEnv *, jobject, jlong); +/* + * Class: android_view_View + * Method: native_setBackgroundDrawable + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_android_view_View_native_1setBackgroundDrawable + (JNIEnv *, jobject, jlong, jlong); + /* * Class: android_view_View * Method: nativeInvalidate diff --git a/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c b/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c new file mode 100644 index 00000000..7af21f81 --- /dev/null +++ b/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c @@ -0,0 +1,13 @@ +#include + +#include "../defines.h" +#include "../generated_headers/android_graphics_drawable_Drawable.h" + +JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1paintable_1from_1path(JNIEnv *env, jclass class, jstring pathStr) { + const char *path = (*env)->GetStringUTFChars(env, pathStr, NULL); + + GdkPaintable *paintable = GDK_PAINTABLE(gdk_texture_new_from_filename(path, NULL)); + + (*env)->ReleaseStringUTFChars(env, pathStr, path); + return _INTPTR(paintable); +} diff --git a/src/api-impl-jni/views/android_view_View.c b/src/api-impl-jni/views/android_view_View.c index d9336fff..f2854cf0 100644 --- a/src/api-impl-jni/views/android_view_View.c +++ b/src/api-impl-jni/views/android_view_View.c @@ -405,3 +405,9 @@ JNIEXPORT void JNICALL Java_android_view_View_setBackgroundColor(JNIEnv *env, jo gtk_style_context_add_provider(gtk_widget_get_style_context(gtk_widget_get_parent(widget)), GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } + +JNIEXPORT void JNICALL Java_android_view_View_native_1setBackgroundDrawable(JNIEnv *env, jobject this, jlong widget_ptr, jlong paintable_ptr) { + GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr)); + GdkPaintable *paintable = GDK_PAINTABLE(_PTR(paintable_ptr)); + wrapper_widget_set_background(WRAPPER_WIDGET(gtk_widget_get_parent(widget)), paintable); +} diff --git a/src/api-impl-jni/widgets/WrapperWidget.c b/src/api-impl-jni/widgets/WrapperWidget.c index c817cde1..31b9e144 100644 --- a/src/api-impl-jni/widgets/WrapperWidget.c +++ b/src/api-impl-jni/widgets/WrapperWidget.c @@ -92,6 +92,8 @@ void wrapper_widget_allocate(GtkWidget *widget, int width, int height, int basel gtk_widget_size_allocate(wrapper->child, &allocation, baseline); if (wrapper->sk_area) gtk_widget_size_allocate(wrapper->sk_area, &allocation, baseline); + if (wrapper->background) + gtk_widget_size_allocate(wrapper->background, &allocation, baseline); } static void wrapper_widget_class_init(WrapperWidgetClass *class) @@ -172,3 +174,12 @@ void wrapper_widget_set_layout_params(WrapperWidget *wrapper, int width, int hei wrapper->layout_width = width; wrapper->layout_height = height; } + +void wrapper_widget_set_background(WrapperWidget *wrapper, GdkPaintable *paintable) +{ + if (!wrapper->background) { + wrapper->background = gtk_picture_new(); + gtk_widget_insert_after(wrapper->background, GTK_WIDGET(wrapper), NULL); + } + gtk_picture_set_paintable(GTK_PICTURE(wrapper->background), paintable); +} diff --git a/src/api-impl-jni/widgets/WrapperWidget.h b/src/api-impl-jni/widgets/WrapperWidget.h index c73dcc17..01fceb90 100644 --- a/src/api-impl-jni/widgets/WrapperWidget.h +++ b/src/api-impl-jni/widgets/WrapperWidget.h @@ -11,6 +11,7 @@ struct _WrapperWidget GtkWidget parent_instance; GtkWidget *child; GtkWidget *sk_area; + GtkWidget *background; JavaVM *jvm; jobject jobj; jobject canvas; @@ -31,6 +32,7 @@ void wrapper_widget_set_child(WrapperWidget *parent, GtkWidget *child); void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj); void wrapper_widget_queue_draw(WrapperWidget *wrapper); void wrapper_widget_set_layout_params(WrapperWidget *wrapper, int width, int height); +void wrapper_widget_set_background(WrapperWidget *wrapper, GdkPaintable *paintable); void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject on_touch_listener); diff --git a/src/api-impl/android/content/res/Resources.java b/src/api-impl/android/content/res/Resources.java index 5938c109..7d762621 100644 --- a/src/api-impl/android/content/res/Resources.java +++ b/src/api-impl/android/content/res/Resources.java @@ -19,6 +19,7 @@ package android.content.res; import android.content.Context; import android.content.pm.ActivityInfo; import android.icu.text.PluralRules; +import android.graphics.drawable.ColorDrawable; // import android.graphics.Movie; import android.graphics.drawable.Drawable; // import android.graphics.drawable.ColorDrawable; @@ -48,7 +49,6 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; class Movie {} -class ColorDrawable {} class ConstantState {} @@ -2017,7 +2017,7 @@ public class Resources { final String name = getResourceName(id); if (name != null) android.util.Log.d("PreloadDrawable", name); } - } + }*/ boolean isColorDrawable = false; if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && @@ -2027,6 +2027,8 @@ public class Resources { final long key = isColorDrawable ? value.data : (((long) value.assetCookie) << 32) | value.data; + Drawable dr = null; + /* Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key); if (dr != null) { @@ -2040,7 +2042,7 @@ public class Resources { } if (cs != null) { dr = cs.newDrawable(this); - } else { + } else*/ { if (isColorDrawable) { dr = new ColorDrawable(value.data); } @@ -2089,8 +2091,7 @@ public class Resources { InputStream is = mAssets.openNonAsset( value.assetCookie, file, AssetManager.ACCESS_STREAMING); // System.out.println("Opened file " + file + ": " + is); - dr = null/*Drawable.createFromResourceStream(this, value, is, - file, null)* /; + dr = Drawable.createFromResourceStream(this, value, is, file, null); is.close(); // System.out.println("Created stream: " + dr); } catch (Exception e) { @@ -2108,7 +2109,7 @@ public class Resources { if (dr != null) { dr.setChangingConfigurations(value.changingConfigurations); - cs = dr.getConstantState(); + /* cs = dr.getConstantState(); if (cs != null) { if (mPreloading) { final int changingConfigs = cs.getChangingConfigurations(); @@ -2145,12 +2146,10 @@ public class Resources { } } } - } + }*/ } return dr; - */ - return null; } private Drawable getCachedDrawable( diff --git a/src/api-impl/android/graphics/drawable/Drawable.java b/src/api-impl/android/graphics/drawable/Drawable.java index 27fa726e..a281290e 100644 --- a/src/api-impl/android/graphics/drawable/Drawable.java +++ b/src/api-impl/android/graphics/drawable/Drawable.java @@ -1,17 +1,35 @@ package android.graphics.drawable; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import android.content.res.ColorStateList; import android.content.res.Resources; +import android.content.res.XmlResourceParser; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.Rect; +import android.util.TypedValue; -public abstract class Drawable { +public class Drawable { public static interface Callback {} private Rect mBounds = new Rect(); private int[] mStateSet = new int[0]; + public long paintable; + + public Drawable() {} + + public Drawable(long paintable) { + this.paintable = paintable; + } public int getChangingConfigurations() { return 0; @@ -38,7 +56,7 @@ public abstract class Drawable { return mBounds; } - public abstract void draw(Canvas canvas); + public void draw(Canvas canvas) {} public boolean setState(int[] stateSet) { this.mStateSet = stateSet; @@ -89,4 +107,36 @@ public abstract class Drawable { public void setTintMode(PorterDuff.Mode tintMode) {} public boolean isProjected () {return false;} + + public static Drawable createFromXml(Resources resources, XmlResourceParser parser) throws XmlPullParserException, IOException { + int type; + while ((type=parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT); + if (type != XmlPullParser.START_TAG) + throw new XmlPullParserException("No start tag found"); + if ("selector".equals(parser.getName())) { + StateListDrawable drawable = new StateListDrawable(); + drawable.inflate(resources, parser, parser, null); + return drawable; + } + return null; + } + + public static Drawable createFromResourceStream(Resources resources, TypedValue value, InputStream is, String file, + Object object) { + Path path = Paths.get(android.os.Environment.getExternalStorageDirectory().getPath(), file); + if (!Files.exists(path)) { + try (InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(file)) { + if (inputStream != null) { + Files.createDirectories(path.getParent()); + Files.copy(inputStream, path); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + long paintable = native_paintable_from_path(path.toString()); + return new Drawable(paintable); + } + + protected static native long native_paintable_from_path(String path); } diff --git a/src/api-impl/android/graphics/drawable/StateListDrawable.java b/src/api-impl/android/graphics/drawable/StateListDrawable.java index a6c7551a..a2ce1417 100644 --- a/src/api-impl/android/graphics/drawable/StateListDrawable.java +++ b/src/api-impl/android/graphics/drawable/StateListDrawable.java @@ -1,6 +1,15 @@ package android.graphics.drawable; +import java.io.IOException; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.content.res.Resources; +import android.content.res.Resources.Theme; import android.graphics.Canvas; +import android.util.AttributeSet; +import android.util.Slog; public class StateListDrawable extends Drawable { @@ -11,5 +20,16 @@ public class StateListDrawable extends Drawable { } public void addState(int[] stateSet, Drawable drawable) {} + + public void inflate(Resources resources, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { + while (parser.next() != XmlPullParser.END_DOCUMENT) { + if ("item".equals(parser.getName())) { + int resid = attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/android", "drawable", -1); + Drawable drawable = resources.getDrawable(resid, theme); + this.paintable = drawable.paintable; + Slog.i("StateListDrawable", "item resid = " + resid + ", paintable = " + drawable.paintable); + } + } + } } diff --git a/src/api-impl/android/view/View.java b/src/api-impl/android/view/View.java index 86ab783a..7f9deee5 100644 --- a/src/api-impl/android/view/View.java +++ b/src/api-impl/android/view/View.java @@ -930,6 +930,7 @@ public class View extends Object { protected native void native_measure(long widget, int widthMeasureSpec, int heightMeasureSpec, boolean isComplex); protected native void native_layout(long widget, int l, int t, int r, int b); protected native void native_requestLayout(long widget); + protected native void native_setBackgroundDrawable(long widget, long paintable); // --- stubs @@ -1005,8 +1006,8 @@ public class View extends Object { this.visibility = visibility; } public void setPadding(int left, int top, int right, int bottom) {} - public void setBackgroundResource(int resid) { -// Slog.w(TAG, "*** setBackgroundResource: " + getString(resid)); + public void setBackgroundResource(int resid) throws Exception { + setBackgroundDrawable(getResources().getDrawable(resid)); } public void getHitRect(Rect outRect) {} @@ -1243,7 +1244,9 @@ public class View extends Object { layout(left + offset, top, right + offset, bottom); } - public void setBackgroundDrawable(Drawable backgroundDrawable) {} + public void setBackgroundDrawable(Drawable backgroundDrawable) { + native_setBackgroundDrawable(widget, backgroundDrawable != null ? backgroundDrawable.paintable : 0); + } public int getOverScrollMode() {return 0;}