From 4bb5dfd86e596153f3d7f9c1ea6c8af43a9ef72a Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Tue, 18 Feb 2025 18:58:58 +0100 Subject: [PATCH] Paint: implement textAlign and text bounds --- .../android_graphics_Paint.h | 16 ++++++++++++ src/api-impl-jni/graphics/AndroidPaint.h | 2 ++ .../graphics/android_graphics_GskCanvas.c | 7 +++++ .../graphics/android_graphics_Paint.c | 26 +++++++++++++++++++ src/api-impl/android/graphics/Paint.java | 26 ++++++++++++++----- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/src/api-impl-jni/generated_headers/android_graphics_Paint.h b/src/api-impl-jni/generated_headers/android_graphics_Paint.h index 16fd234c..59eed0c1 100644 --- a/src/api-impl-jni/generated_headers/android_graphics_Paint.h +++ b/src/api-impl-jni/generated_headers/android_graphics_Paint.h @@ -161,6 +161,22 @@ JNIEXPORT jfloat JNICALL Java_android_graphics_Paint_native_1get_1text_1size JNIEXPORT void JNICALL Java_android_graphics_Paint_native_1set_1color_1filter (JNIEnv *, jclass, jlong, jint, jint); +/* + * Class: android_graphics_Paint + * Method: native_get_text_bounds + * Signature: (JLjava/lang/String;Landroid/graphics/Rect;)V + */ +JNIEXPORT void JNICALL Java_android_graphics_Paint_native_1get_1text_1bounds + (JNIEnv *, jclass, jlong, jstring, jobject); + +/* + * Class: android_graphics_Paint + * Method: native_set_text_align + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_android_graphics_Paint_native_1set_1text_1align + (JNIEnv *, jclass, jlong, jint); + #ifdef __cplusplus } #endif diff --git a/src/api-impl-jni/graphics/AndroidPaint.h b/src/api-impl-jni/graphics/AndroidPaint.h index 429aa867..9483ab36 100644 --- a/src/api-impl-jni/graphics/AndroidPaint.h +++ b/src/api-impl-jni/graphics/AndroidPaint.h @@ -1,3 +1,4 @@ +#include "pango/pango-layout.h" #include #include #include @@ -6,6 +7,7 @@ struct AndroidPaint { GdkRGBA color; GskStroke *gsk_stroke; PangoFontDescription *font; + PangoAlignment alignment; graphene_matrix_t color_matrix; graphene_vec4_t color_offset; bool is_fill:1; diff --git a/src/api-impl-jni/graphics/android_graphics_GskCanvas.c b/src/api-impl-jni/graphics/android_graphics_GskCanvas.c index c7eee145..f1b20122 100644 --- a/src/api-impl-jni/graphics/android_graphics_GskCanvas.c +++ b/src/api-impl-jni/graphics/android_graphics_GskCanvas.c @@ -102,6 +102,13 @@ JNIEXPORT void JNICALL Java_android_graphics_GskCanvas_native_1drawText(JNIEnv * const char *str = (*env)->GetStringUTFChars(env, text, NULL); pango_layout_set_text(layout, str, -1); (*env)->ReleaseStringUTFChars(env, text, str); + PangoRectangle rect; + pango_layout_get_pixel_extents(layout, NULL, &rect); + y -= rect.height; + if (paint->alignment == PANGO_ALIGN_CENTER) + x -= rect.width / 2.f; + else if (paint->alignment == PANGO_ALIGN_RIGHT) + x -= rect.width; gtk_snapshot_translate(snapshot, &GRAPHENE_POINT_INIT(x, y)); gtk_snapshot_append_layout(snapshot, layout, &paint->color); gtk_snapshot_translate(snapshot, &GRAPHENE_POINT_INIT(-x, -y)); diff --git a/src/api-impl-jni/graphics/android_graphics_Paint.c b/src/api-impl-jni/graphics/android_graphics_Paint.c index 84cb59b2..e3563563 100644 --- a/src/api-impl-jni/graphics/android_graphics_Paint.c +++ b/src/api-impl-jni/graphics/android_graphics_Paint.c @@ -1,5 +1,6 @@ #include #include +#include #include "AndroidPaint.h" #include "../defines.h" @@ -131,3 +132,28 @@ JNIEXPORT void JNICALL Java_android_graphics_Paint_native_1set_1color_1filter(JN graphene_vec4_init(&paint->color_offset, ((color >> 16) & 0xFF) / 255.f, ((color >> 8) & 0xFF) / 255.f, ((color >> 0) & 0xFF) / 255.f, 0); paint->use_color_filter = mode != -1; } + +extern GtkWidget *window; + +JNIEXPORT void JNICALL Java_android_graphics_Paint_native_1get_1text_1bounds(JNIEnv *env, jclass clazz, jlong paint_ptr, jstring text_ptr, jobject bounds) +{ + struct AndroidPaint *paint = _PTR(paint_ptr); + PangoLayout *layout = pango_layout_new(gtk_widget_get_pango_context(window)); + pango_layout_set_font_description(layout, paint->font); + const char *str = (*env)->GetStringUTFChars(env, text_ptr, NULL); + pango_layout_set_text(layout, str, -1); + (*env)->ReleaseStringUTFChars(env, text_ptr, str); + PangoRectangle rect; + pango_layout_get_pixel_extents(layout, NULL, &rect); + _SET_INT_FIELD(bounds, "left", rect.x); + _SET_INT_FIELD(bounds, "top", rect.y); + _SET_INT_FIELD(bounds, "right", rect.x + rect.width); + _SET_INT_FIELD(bounds, "bottom", rect.y + rect.height); + g_object_unref(layout); +} + +JNIEXPORT void JNICALL Java_android_graphics_Paint_native_1set_1text_1align(JNIEnv *env, jclass clazz, jlong paint_ptr, jint align) +{ + struct AndroidPaint *paint = _PTR(paint_ptr); + paint->alignment = align; +} diff --git a/src/api-impl/android/graphics/Paint.java b/src/api-impl/android/graphics/Paint.java index 72b412cb..cd0d0c89 100644 --- a/src/api-impl/android/graphics/Paint.java +++ b/src/api-impl/android/graphics/Paint.java @@ -60,11 +60,18 @@ public class Paint { public Typeface setTypeface(Typeface typeface) { return typeface; } - public void getTextBounds(String text, int start, int end, Rect bounds) {} - public void getTextBounds(char[] text, int index, int count, Rect bounds) {} + public void getTextBounds(String text, int start, int end, Rect bounds) { + if (end > text.length()) + end = text.length(); + native_get_text_bounds(paint, text.substring(start, end), bounds); + } + public void getTextBounds(char[] text, int index, int count, Rect bounds) { + native_get_text_bounds(paint, new String(text, index, count), bounds); + } public int getTextWidths(String text, int start, int end, float[] widths) { - // TODO fix it - return 0; + Rect bounds = new Rect(); + native_get_text_bounds(paint, text.substring(start, end), bounds); + return bounds.width(); } public void setFilterBitmap(boolean filter) {} @@ -78,7 +85,7 @@ public class Paint { } public float ascent() { - return 10; + return -getTextSize(); } public float measureText(char[] text, int index, int count) { return 10; } @@ -253,8 +260,8 @@ public class Paint { } public enum Align { - CENTER, LEFT, + CENTER, RIGHT, } @@ -270,7 +277,10 @@ public class Paint { return new Typeface(); } - public void setTextAlign(Align align) {} + public void setTextAlign(Align align) { + this.align = align; + native_set_text_align(paint, align.ordinal()); + } public Shader getShader() { return shader; @@ -343,4 +353,6 @@ public class Paint { private static native void native_set_text_size(long paint, float size); private static native float native_get_text_size(long paint); private static native void native_set_color_filter(long paint, int mode, int color); + private static native void native_get_text_bounds(long paint, String text, Rect bounds); + private static native void native_set_text_align(long paint, int align); }