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
main-executable: handle drawable-based app icons by rendering them into SVG
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
#define _GET_FLOAT_FIELD(object, field) ((*env)->GetFloatField(env, object, _FIELD_ID(_CLASS(object), field, "F")))
|
||||
#define _SET_FLOAT_FIELD(object, field, value) ((*env)->SetFloatField(env, object, _FIELD_ID(_CLASS(object), field, "F"), value))
|
||||
#define _SET_STATIC_INT_FIELD(class, field, value) ((*env)->SetStaticIntField(env, class, _STATIC_FIELD_ID(class, field, "I"), value))
|
||||
#define _SET_STATIC_BOOL_FIELD(class, field, value) ((*env)->SetStaticBooleanField(env, class, _STATIC_FIELD_ID(class, field, "Z"), value))
|
||||
#define _SET_STATIC_OBJ_FIELD(class, field, type, value) ((*env)->SetStaticObjectField(env, class, _STATIC_FIELD_ID(class, field, type), value))
|
||||
#define _GET_STATIC_OBJ_FIELD(class, field, type) ((*env)->GetStaticObjectField(env, class, _STATIC_FIELD_ID(class, field, type)))
|
||||
#define _GET_BYTE_ARRAY_ELEMENTS(b_array) ((*env)->GetByteArrayElements(env, b_array, NULL))
|
||||
|
||||
@@ -162,6 +162,7 @@ void set_up_handle_cache(JNIEnv *env)
|
||||
|
||||
handle_cache.application.class = _REF((*env)->FindClass(env, "android/app/Application"));
|
||||
handle_cache.application.get_app_icon_path = _METHOD(handle_cache.application.class, "get_app_icon_path", "()Ljava/lang/String;");
|
||||
handle_cache.application.get_app_icon_paintable = _METHOD(handle_cache.application.class, "get_app_icon_paintable", "()J");
|
||||
|
||||
handle_cache.looper.class = _REF((*env)->FindClass(env, "android/os/Looper"));
|
||||
handle_cache.looper.loop = _STATIC_METHOD(handle_cache.looper.class, "loop", "()V");
|
||||
|
||||
@@ -107,6 +107,7 @@ struct handle_cache {
|
||||
struct {
|
||||
jclass class;
|
||||
jmethodID get_app_icon_path;
|
||||
jmethodID get_app_icon_paintable;
|
||||
} application;
|
||||
struct {
|
||||
jclass class;
|
||||
|
||||
@@ -2,6 +2,7 @@ package android.app;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.content.res.Configuration;
|
||||
import android.R;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.pm.PackageParser;
|
||||
@@ -10,7 +11,22 @@ public class Application extends ContextWrapper {
|
||||
public long native_window;
|
||||
|
||||
private String get_app_icon_path() {
|
||||
return getString(pkg.applicationInfo.icon);
|
||||
String icon_path = null;
|
||||
try {
|
||||
icon_path = getString(pkg.applicationInfo.icon);
|
||||
} catch (android.content.res.Resources.NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (icon_path == null) {
|
||||
icon_path = getString(R.mipmap.sym_def_app_icon);
|
||||
} else if (icon_path.endsWith(".xml")) {
|
||||
icon_path = null;
|
||||
}
|
||||
return icon_path;
|
||||
}
|
||||
|
||||
private long get_app_icon_paintable() {
|
||||
return getPackageManager().getApplicationIcon(pkg.applicationInfo).paintable;
|
||||
}
|
||||
|
||||
String get_app_label() {
|
||||
|
||||
@@ -2613,7 +2613,7 @@ public class PackageManager {
|
||||
* @see #getApplicationIcon(String)
|
||||
*/
|
||||
public Drawable getApplicationIcon(ApplicationInfo info) {
|
||||
return null;
|
||||
return Context.this_application.getDrawable(info.icon);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// for dladdr
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <cairo-svg.h>
|
||||
#include <gdk/wayland/gdkwayland.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <libportal/portal.h>
|
||||
@@ -176,6 +177,13 @@ static void dynamic_launcher_ready_callback(GObject *portal, GAsyncResult *res,
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static cairo_status_t cairo_write_func_gstring(void *closure, const unsigned char *data, unsigned int length)
|
||||
{
|
||||
GString *str = closure;
|
||||
g_string_append_len(str, (gchar *)data, length);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// this is exported by the shim bionic linker
|
||||
void dl_parse_library_path(const char *path, char *delim);
|
||||
|
||||
@@ -561,7 +569,9 @@ static void open(GtkApplication *app, GFile **files, gint nfiles, const gchar *h
|
||||
(*env)->ExceptionDescribe(env);
|
||||
|
||||
GVariant *icon_serialized = NULL;
|
||||
if (app_icon_path && !d->install_internal) {
|
||||
if (!d->install_internal) {
|
||||
if (app_icon_path) {
|
||||
/* we can import the icon as-is */
|
||||
extract_from_apk(app_icon_path, app_icon_path);
|
||||
char *app_icon_path_full = g_strdup_printf("%s/%s", app_data_dir, app_icon_path);
|
||||
GMappedFile *icon_file = g_mapped_file_new(app_icon_path_full, FALSE, NULL);
|
||||
@@ -572,6 +582,27 @@ static void open(GtkApplication *app, GFile **files, gint nfiles, const gchar *h
|
||||
g_bytes_unref(icon_bytes);
|
||||
g_mapped_file_unref(icon_file);
|
||||
g_free(app_icon_path_full);
|
||||
} else {
|
||||
/* the icon is a generalized Drawable, let's render it into an SVG */
|
||||
_SET_STATIC_BOOL_FIELD((*env)->FindClass(env, "android/graphics/drawable/VectorDrawable"), "direct_draw_override", true);
|
||||
GdkPaintable *icon_paintable = _PTR((*env)->CallLongMethod(env, application_object, handle_cache.application.get_app_icon_paintable));
|
||||
GString *svg_string = g_string_new("");
|
||||
cairo_surface_t *svg_surface = cairo_svg_surface_create_for_stream(cairo_write_func_gstring, svg_string, 108, 108);
|
||||
cairo_t *cr = cairo_create(svg_surface);
|
||||
GdkSnapshot *snapshot = gtk_snapshot_new();
|
||||
gdk_paintable_snapshot(icon_paintable, snapshot, 108, 108);
|
||||
GskRenderNode *node = gtk_snapshot_to_node(snapshot);
|
||||
gsk_render_node_draw(node, cr);
|
||||
gsk_render_node_unref(node);
|
||||
g_object_unref(snapshot);
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_destroy(svg_surface);
|
||||
GBytes *icon_bytes = g_string_free_to_bytes(svg_string);
|
||||
GIcon *icon = g_bytes_icon_new(icon_bytes);
|
||||
icon_serialized = g_icon_serialize(icon);
|
||||
g_object_unref(icon);
|
||||
g_bytes_unref(icon_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
gchar *dest_name = g_strdup_printf("%s.apk", package_name);
|
||||
|
||||
Reference in New Issue
Block a user