You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
src/api-impl: use skia instead of cairo
Using the C API provided by SkiaSharp's skia fork instead of using cairo significantly improves performance. The API is also closer to the android Canvas API, which makes the implementation more straightforward.
This commit is contained in:
@@ -4,46 +4,10 @@
|
||||
#include "../util.h"
|
||||
#include "../drawables/ninepatch.h"
|
||||
|
||||
#include "../sk_area/sk_area.h"
|
||||
|
||||
#include "WrapperWidget.h"
|
||||
|
||||
/**
|
||||
* gdk_texture_new_for_surface:
|
||||
* @surface: a cairo image surface
|
||||
*
|
||||
* Creates a new texture object representing the surface.
|
||||
*
|
||||
* @surface must be an image surface with format CAIRO_FORMAT_ARGB32.
|
||||
*
|
||||
* Returns: a new `GdkTexture`
|
||||
*/
|
||||
GdkTexture * gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes;
|
||||
|
||||
g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
|
||||
g_return_val_if_fail (cairo_image_surface_get_width (surface) > 0, NULL);
|
||||
g_return_val_if_fail (cairo_image_surface_get_height (surface) > 0, NULL);
|
||||
|
||||
bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_height (surface)
|
||||
* cairo_image_surface_get_stride (surface),
|
||||
(GDestroyNotify) cairo_surface_destroy,
|
||||
cairo_surface_reference (surface));
|
||||
|
||||
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_DEFAULT,
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
G_DEFINE_TYPE(WrapperWidget, wrapper_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
static void wrapper_widget_init (WrapperWidget *wrapper_widget)
|
||||
@@ -66,54 +30,27 @@ static void wrapper_widget_dispose(GObject *wrapper_widget)
|
||||
G_OBJECT_CLASS (wrapper_widget_parent_class)->dispose (wrapper_widget);
|
||||
}
|
||||
|
||||
void wrapper_snapshot(GtkWidget* widget, GtkSnapshot* snapshot)
|
||||
void skia_draw_func(SKArea *sk_area, sk_canvas_t *canvas, WrapperWidget *wrapper_widget)
|
||||
{
|
||||
struct ninepatch_t *ninepatch = g_object_get_data(G_OBJECT(widget), "background_ninepatch");
|
||||
|
||||
if(ninepatch && 0) {
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocation(widget, &alloc);
|
||||
|
||||
ninepatch_stretch(ninepatch, alloc.width, alloc.height);
|
||||
|
||||
cairo_surface_t *surface = ninepatch_to_surface(ninepatch);
|
||||
|
||||
// GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, ninepatch->__w, ninepatch->__h);
|
||||
// GdkTexture *texture = gdk_texture_new_for_pixbuf(pixbuf);
|
||||
GdkTexture *texture = gdk_texture_new_for_surface(surface);
|
||||
|
||||
gtk_snapshot_append_texture(snapshot, texture, &GRAPHENE_RECT_INIT(0, 0, ninepatch->__w, ninepatch->__h));
|
||||
|
||||
cairo_surface_destroy(surface);
|
||||
// g_object_unref(pixbuf);
|
||||
g_object_unref(texture);
|
||||
JNIEnv *env;
|
||||
(*wrapper_widget->jvm)->GetEnv(wrapper_widget->jvm, (void**)&env, JNI_VERSION_1_6);
|
||||
if(wrapper_widget->canvas == NULL) {
|
||||
wrapper_widget->canvas = _REF((*env)->NewObject(env, handle_cache.canvas.class, handle_cache.canvas.constructor, _INTPTR(canvas), 0));
|
||||
} else {
|
||||
_SET_LONG_FIELD(wrapper_widget->canvas, "skia_canvas", _INTPTR(canvas));
|
||||
}
|
||||
gtk_widget_snapshot_child(widget, gtk_widget_get_first_child(widget), snapshot);
|
||||
|
||||
// if onDraw method is overwritten call it now
|
||||
WrapperWidget *wrapper_widget = WRAPPER_WIDGET(widget);
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocation(widget, &alloc);
|
||||
if (wrapper_widget->draw_method) {
|
||||
cairo_t *cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT(0, 0, alloc.width, alloc.height));
|
||||
(*env)->CallVoidMethod(env, wrapper_widget->jobj, wrapper_widget->draw_method, wrapper_widget->canvas);
|
||||
|
||||
JNIEnv *env;
|
||||
(*wrapper_widget->jvm)->GetEnv(wrapper_widget->jvm, (void**)&env, JNI_VERSION_1_6);
|
||||
if(wrapper_widget->canvas == NULL) {
|
||||
wrapper_widget->canvas = _REF((*env)->NewObject(env, handle_cache.canvas.class, handle_cache.canvas.constructor, _INTPTR(cr), 0));
|
||||
} else {
|
||||
_SET_LONG_FIELD(wrapper_widget->canvas, "cairo_context", _INTPTR(cr));
|
||||
}
|
||||
|
||||
(*env)->CallVoidMethod(env, wrapper_widget->jobj, wrapper_widget->draw_method, wrapper_widget->canvas);
|
||||
|
||||
if((*env)->ExceptionCheck(env))
|
||||
(*env)->ExceptionDescribe(env);
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
if((*env)->ExceptionCheck(env))
|
||||
(*env)->ExceptionDescribe(env);
|
||||
}
|
||||
|
||||
/*void wrapper_snapshot(GtkWidget* widget, GtkSnapshot* snapshot)
|
||||
{
|
||||
gtk_widget_snapshot_child(widget, gtk_widget_get_first_child(widget), snapshot);
|
||||
}*/
|
||||
|
||||
|
||||
static void wrapper_widget_class_init(WrapperWidgetClass *class)
|
||||
{
|
||||
@@ -122,7 +59,7 @@ static void wrapper_widget_class_init(WrapperWidgetClass *class)
|
||||
|
||||
object_class->dispose = wrapper_widget_dispose;
|
||||
|
||||
widget_class->snapshot = wrapper_snapshot;
|
||||
// widget_class->snapshot = wrapper_snapshot;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type(widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
}
|
||||
@@ -156,6 +93,14 @@ static void on_mapped(GtkWidget* self, gpointer data)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: this is used in one other place as well, should probably go in util.c or gtk_util.c?
|
||||
gboolean tick_callback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data)
|
||||
{
|
||||
gtk_widget_queue_draw(widget);
|
||||
gtk_widget_queue_draw(gtk_widget_get_parent(widget));
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj)
|
||||
{
|
||||
JavaVM *jvm;
|
||||
@@ -163,9 +108,15 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
|
||||
wrapper->jvm = jvm;
|
||||
wrapper->jobj = _REF(jobj);
|
||||
jmethodID draw_method = _METHOD(_CLASS(jobj), "onDraw", "(Landroid/graphics/Canvas;)V");
|
||||
if (draw_method != handle_cache.view.onDraw)
|
||||
if (draw_method != handle_cache.view.onDraw) {
|
||||
wrapper->draw_method = draw_method;
|
||||
|
||||
GtkWidget *sk_area = sk_area_new();
|
||||
sk_area_set_draw_func(SK_AREA_WIDGET(sk_area), skia_draw_func, wrapper);
|
||||
gtk_widget_insert_before(sk_area, GTK_WIDGET(wrapper), NULL);
|
||||
gtk_widget_add_tick_callback(sk_area, tick_callback, NULL, NULL);
|
||||
}
|
||||
|
||||
jmethodID measure_method = _METHOD(_CLASS(jobj), "onMeasure", "(II)V");
|
||||
if (measure_method != handle_cache.view.onMeasure) {
|
||||
wrapper->measure_method = measure_method;
|
||||
|
||||
Reference in New Issue
Block a user