diff --git a/meson.build b/meson.build index 83093fb8..04c80cdc 100644 --- a/meson.build +++ b/meson.build @@ -97,6 +97,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/graphics/NinePatchPaintable.c', 'src/api-impl-jni/graphics/NinePatchPaintable.c', 'src/api-impl-jni/graphics/android_graphics_BitmapFactory.c', + 'src/api-impl-jni/graphics/android_graphics_GskCanvas.c', 'src/api-impl-jni/graphics/android_graphics_Matrix.c', 'src/api-impl-jni/graphics/android_graphics_Path.c', 'src/api-impl-jni/graphics/android_graphics_Typeface.c', diff --git a/src/api-impl-jni/generated_headers/android_graphics_GskCanvas.h b/src/api-impl-jni/generated_headers/android_graphics_GskCanvas.h new file mode 100644 index 00000000..243c43f0 --- /dev/null +++ b/src/api-impl-jni/generated_headers/android_graphics_GskCanvas.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class android_graphics_GskCanvas */ + +#ifndef _Included_android_graphics_GskCanvas +#define _Included_android_graphics_GskCanvas +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: android_graphics_GskCanvas + * Method: native_drawBitmap + * Signature: (JJIIII)V + */ +JNIEXPORT void JNICALL Java_android_graphics_GskCanvas_native_1drawBitmap + (JNIEnv *, jobject, jlong, jlong, jint, jint, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif 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 index 57c39e84..0366f0c1 100644 --- a/src/api-impl-jni/generated_headers/android_graphics_drawable_Drawable.h +++ b/src/api-impl-jni/generated_headers/android_graphics_drawable_Drawable.h @@ -15,6 +15,14 @@ extern "C" { JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1paintable_1from_1path (JNIEnv *, jclass, jstring); +/* + * Class: android_graphics_drawable_Drawable + * Method: native_constructor + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1constructor + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif diff --git a/src/api-impl-jni/graphics/android_graphics_GskCanvas.c b/src/api-impl-jni/graphics/android_graphics_GskCanvas.c new file mode 100644 index 00000000..df5cbb8a --- /dev/null +++ b/src/api-impl-jni/graphics/android_graphics_GskCanvas.c @@ -0,0 +1,16 @@ +#include +#include + +#include "../defines.h" +#include "../util.h" + +#include "../generated_headers/android_graphics_GskCanvas.h" + +JNIEXPORT void JNICALL Java_android_graphics_GskCanvas_native_1drawBitmap(JNIEnv *env, jclass this_class, jlong snapshot_ptr, jlong pixbuf_ptr, jint x, jint y, jint width, jint height) +{ + GdkSnapshot *snapshot = (GdkSnapshot *)_PTR(snapshot_ptr); + GdkPixbuf *pixbuf = (GdkPixbuf *)_PTR(pixbuf_ptr); + GdkTexture *texture = gdk_texture_new_for_pixbuf(pixbuf); + gtk_snapshot_append_texture(snapshot, texture, &GRAPHENE_RECT_INIT(x, y, width, height)); + g_object_unref(texture); +} diff --git a/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c b/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c index f8969ff2..5a023e60 100644 --- a/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c +++ b/src/api-impl-jni/graphics/android_graphics_drawable_Drawable.c @@ -2,6 +2,7 @@ #include #include "../defines.h" +#include "../util.h" #include "NinePatchPaintable.h" #include "../generated_headers/android_graphics_drawable_Drawable.h" @@ -20,3 +21,49 @@ JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1paintabl (*env)->ReleaseStringUTFChars(env, pathStr, path); return _INTPTR(paintable); } + +struct _JavaPaintable { + GObject parent_instance; + jobject drawable; +}; +G_DECLARE_FINAL_TYPE(JavaPaintable, java_paintable, JAVA, PAINTABLE, GObject) + +static void java_paintable_snapshot(GdkPaintable *gdk_paintable, GdkSnapshot *snapshot, double width, double height) +{ + JNIEnv *env = get_jni_env(); + JavaPaintable *paintable = JAVA_PAINTABLE(gdk_paintable); + jclass canvas_class = (*env)->FindClass(env, "android/graphics/GskCanvas"); + jmethodID canvas_constructor = _METHOD(canvas_class, "", "(J)V"); + jobject canvas = (*env)->NewObject(env, canvas_class, canvas_constructor, _INTPTR(snapshot)); + (*env)->CallVoidMethod(env, paintable->drawable, handle_cache.drawable.setBounds, 0, 0, (int)width, (int)height); + (*env)->CallVoidMethod(env, paintable->drawable, handle_cache.drawable.draw, canvas); + if ((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + (*env)->DeleteLocalRef(env, canvas); + (*env)->DeleteLocalRef(env, canvas_class); +} + +static void java_paintable_init(JavaPaintable *java_paintable) +{ +} + +static void java_paintable_paintable_init(GdkPaintableInterface *iface) +{ + iface->snapshot = java_paintable_snapshot; +} + +static void java_paintable_class_init(JavaPaintableClass *class) +{ +} + +G_DEFINE_TYPE_WITH_CODE(JavaPaintable, java_paintable, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(GDK_TYPE_PAINTABLE, java_paintable_paintable_init)) + +JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1constructor(JNIEnv *env, jobject this) { + JavaPaintable *paintable = NULL; + if (handle_cache.drawable.draw != _METHOD(_CLASS(this), "draw", "(Landroid/graphics/Canvas;)V")) { + paintable = g_object_new(java_paintable_get_type(), NULL); + paintable->drawable = _REF(this); + } + return _INTPTR(paintable); +} diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index fc82c3cc..f5b61f58 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -144,6 +144,10 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.key_event.class = _REF((*env)->FindClass(env, "android/view/KeyEvent")); handle_cache.key_event.constructor = _METHOD(handle_cache.key_event.class, "", "(II)V"); + + handle_cache.drawable.class = _REF((*env)->FindClass(env, "android/graphics/drawable/Drawable")); + handle_cache.drawable.draw = _METHOD(handle_cache.drawable.class, "draw", "(Landroid/graphics/Canvas;)V"); + handle_cache.drawable.setBounds = _METHOD(handle_cache.drawable.class, "setBounds", "(IIII)V"); } void extract_from_apk(const char *path, const char *target) { diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index b40135f6..420414d5 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -100,6 +100,11 @@ struct handle_cache { jclass class; jmethodID constructor; } key_event; + struct { + jclass class; + jmethodID draw; + jmethodID setBounds; + } drawable; }; extern struct handle_cache handle_cache; diff --git a/src/api-impl/android/graphics/Canvas.java b/src/api-impl/android/graphics/Canvas.java index 4052403e..b647f669 100644 --- a/src/api-impl/android/graphics/Canvas.java +++ b/src/api-impl/android/graphics/Canvas.java @@ -81,7 +81,7 @@ public class Canvas { * @param px The x-coord for the pivot point (unchanged by the rotation) * @param py The y-coord for the pivot point (unchanged by the rotation) */ - public final void rotate(float degrees, float px, float py) { + public void rotate(float degrees, float px, float py) { native_rotate_and_translate(skia_canvas, widget, degrees, px, py); } // --- diff --git a/src/api-impl/android/graphics/GskCanvas.java b/src/api-impl/android/graphics/GskCanvas.java new file mode 100644 index 00000000..28e3dc49 --- /dev/null +++ b/src/api-impl/android/graphics/GskCanvas.java @@ -0,0 +1,74 @@ +package android.graphics; + +/** + * GskCanvas: + * - implements Canvas for onscreen rendering inside GTKs snapshot function + */ +public class GskCanvas extends Canvas { + private long snapshot; + + public GskCanvas(long snapshot) { + System.out.println("GskCanvas(" + snapshot + ")"); + this.snapshot = snapshot; + } + + @Override + public int save() { + System.out.println("GskCanvas.save()"); + return -1; + } + + @Override + public void restore() { + System.out.println("GskCanvas.restore()"); + } + + @Override + public void translate(float dx, float dy) { + System.out.println("GskCanvas.translate(" + dx + ", " + dy + ")"); + } + + @Override + public void rotate(float degrees) { + System.out.println("GskCanvas.rotate(" + degrees + ")"); + } + + @Override + public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { + native_drawBitmap(snapshot, bitmap.pixbuf, dst.left, dst.top, dst.width(), dst.height()); + } + + @Override + public void drawPath(Path path, Paint paint) { + System.out.println("GskCanvas.drawPath(" + path + ", " + paint + ")"); + } + + @Override + public void drawRect(float left, float top, float right, float bottom, Paint paint) { + System.out.println("GskCanvas.drawRect(" + left + ", " + top + ", " + right + ", " + bottom + ", " + paint + ")"); + } + + @Override + public void rotate(float degrees, float px, float py) { + System.out.println("GskCanvas.rotate(" + degrees + ", " + px + ", " + py + ")"); + } + + @Override + public void drawText(String text, float x, float y, Paint paint) { + System.out.println("GskCanvas.drawText(" + text + ", " + x + ", " + y + ", " + paint + ")"); + } + + @Override + public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { + System.out.println("GskCanvas.drawLine(" + startX + ", " + startY + ", " + stopX + ", " + stopY + ", " + paint + ")"); + } + + @Override + public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { + Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + Rect dst = new Rect((int)left, (int)top, (int)left + bitmap.getWidth(), (int)top + bitmap.getHeight()); + drawBitmap(bitmap, src, dst, paint); + } + + protected native void native_drawBitmap(long snapshot, long pixbuf, int x, int y, int width, int height); +} diff --git a/src/api-impl/android/graphics/drawable/Drawable.java b/src/api-impl/android/graphics/drawable/Drawable.java index 52c497fc..d3c23639 100644 --- a/src/api-impl/android/graphics/drawable/Drawable.java +++ b/src/api-impl/android/graphics/drawable/Drawable.java @@ -28,7 +28,9 @@ public class Drawable { private int[] mStateSet = new int[0]; public long paintable; - public Drawable() {} + public Drawable() { + this.paintable = native_constructor(); + } public Drawable(long paintable) { this.paintable = paintable; @@ -180,4 +182,5 @@ public class Drawable { } protected static native long native_paintable_from_path(String path); + protected native long native_constructor(); } diff --git a/src/api-impl/android/graphics/drawable/GradientDrawable.java b/src/api-impl/android/graphics/drawable/GradientDrawable.java index ca1a77be..35591194 100644 --- a/src/api-impl/android/graphics/drawable/GradientDrawable.java +++ b/src/api-impl/android/graphics/drawable/GradientDrawable.java @@ -1,15 +1,7 @@ package android.graphics.drawable; -import android.graphics.Canvas; - public class GradientDrawable extends Drawable { - @Override - public void draw(Canvas canvas) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'draw'"); - } - public void setColor(int color) {} public void setCornerRadius(float cornerRadius) {} diff --git a/src/api-impl/android/graphics/drawable/InsetDrawable.java b/src/api-impl/android/graphics/drawable/InsetDrawable.java index a5396af4..8224e34a 100644 --- a/src/api-impl/android/graphics/drawable/InsetDrawable.java +++ b/src/api-impl/android/graphics/drawable/InsetDrawable.java @@ -1,6 +1,5 @@ package android.graphics.drawable; -import android.graphics.Canvas; import android.graphics.Rect; public class InsetDrawable extends Drawable { @@ -9,12 +8,6 @@ public class InsetDrawable extends Drawable { super(); } - @Override - public void draw(Canvas canvas) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'draw'"); - } - public boolean getPadding(Rect padding) { return false; } } diff --git a/src/api-impl/android/graphics/drawable/RippleDrawable.java b/src/api-impl/android/graphics/drawable/RippleDrawable.java index b4b0fcfd..cdb92941 100644 --- a/src/api-impl/android/graphics/drawable/RippleDrawable.java +++ b/src/api-impl/android/graphics/drawable/RippleDrawable.java @@ -1,15 +1,9 @@ package android.graphics.drawable; import android.content.res.ColorStateList; -import android.graphics.Canvas; public class RippleDrawable extends Drawable { public RippleDrawable(ColorStateList colorStateList, Drawable drawable, Drawable drawable2) {} - @Override - public void draw(Canvas canvas) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'draw'"); - } } diff --git a/src/api-impl/android/graphics/drawable/ShapeDrawable.java b/src/api-impl/android/graphics/drawable/ShapeDrawable.java index f0dbdc94..f5c1dd5d 100644 --- a/src/api-impl/android/graphics/drawable/ShapeDrawable.java +++ b/src/api-impl/android/graphics/drawable/ShapeDrawable.java @@ -1,6 +1,5 @@ package android.graphics.drawable; -import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.shapes.Shape; @@ -9,11 +8,5 @@ public class ShapeDrawable extends Drawable { public ShapeDrawable(Shape shape) {} public Paint getPaint() {return new Paint();} - - @Override - public void draw(Canvas canvas) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'draw'"); - } } diff --git a/src/api-impl/meson.build b/src/api-impl/meson.build index 16f294be..879222b1 100644 --- a/src/api-impl/meson.build +++ b/src/api-impl/meson.build @@ -161,6 +161,7 @@ hax_jar = jar('hax', [ 'android/graphics/Canvas.java', 'android/graphics/Color.java', 'android/graphics/ColorFilter.java', + 'android/graphics/GskCanvas.java', 'android/graphics/Matrix.java', 'android/graphics/Paint.java', 'android/graphics/Path.java',