From 6ffb0a17199d70e5d4e5fc155897acf0ef2ccac6 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 14 Sep 2023 16:53:04 +0800 Subject: [PATCH] Avert a crash in the Android last resort font driver * java/org/gnu/emacs/EmacsFontDriver.java (FONT_INVALID_CODE): New constant. (hasChar, encodeChar): Accept a jint character code rather than a jchar. * java/org/gnu/emacs/EmacsSdk23FontDriver.java (hasChar) (encodeChar): Return 0 or FONT_INVALID_CODE if the character is not representable in a Java char. * java/org/gnu/emacs/EmacsSdk7FontDriver.java (hasChar): Ditto. * src/androidfont.c (android_init_font_driver): Adjust signature to match. --- java/org/gnu/emacs/EmacsFontDriver.java | 11 +++++++++-- java/org/gnu/emacs/EmacsSdk23FontDriver.java | 10 ++++++++-- java/org/gnu/emacs/EmacsSdk7FontDriver.java | 16 ++++++++++++---- src/androidfont.c | 4 ++-- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/java/org/gnu/emacs/EmacsFontDriver.java b/java/org/gnu/emacs/EmacsFontDriver.java index ff52899a897..798c3cfb032 100644 --- a/java/org/gnu/emacs/EmacsFontDriver.java +++ b/java/org/gnu/emacs/EmacsFontDriver.java @@ -63,6 +63,11 @@ public abstract class EmacsFontDriver public static final int MONO = 100; public static final int CHARCELL = 110; + /* Special glyph codes. */ + public static final int FONT_INVALID_CODE = 0xFFFFFFFF; + + + public static class FontSpec { /* The fields below mean the same as they do in enum @@ -148,15 +153,17 @@ public abstract class EmacsFontDriver } }; + + /* These mean the same as they do in struct font_driver. */ public abstract FontEntity[] list (FontSpec fontSpec); public abstract FontEntity match (FontSpec fontSpec); public abstract String[] listFamilies (); public abstract FontObject openFont (FontEntity fontEntity, int pixelSize); - public abstract int hasChar (FontSpec font, char charCode); + public abstract int hasChar (FontSpec font, int charCode); public abstract void textExtents (FontObject font, int code[], FontMetrics fontMetrics); - public abstract int encodeChar (FontObject fontObject, char charCode); + public abstract int encodeChar (FontObject fontObject, int charCode); public abstract int draw (FontObject fontObject, EmacsGC gc, EmacsDrawable drawable, int[] chars, int x, int y, int backgroundWidth, diff --git a/java/org/gnu/emacs/EmacsSdk23FontDriver.java b/java/org/gnu/emacs/EmacsSdk23FontDriver.java index aaba8dbd166..0752d8064ac 100644 --- a/java/org/gnu/emacs/EmacsSdk23FontDriver.java +++ b/java/org/gnu/emacs/EmacsSdk23FontDriver.java @@ -96,7 +96,7 @@ public final class EmacsSdk23FontDriver extends EmacsSdk7FontDriver @Override public int - hasChar (FontSpec font, char charCode) + hasChar (FontSpec font, int charCode) { Sdk7FontObject fontObject; Paint paint; @@ -109,6 +109,12 @@ public final class EmacsSdk23FontDriver extends EmacsSdk7FontDriver else paint = ((Sdk7FontEntity) font).typeface.typefacePaint; - return paint.hasGlyph (String.valueOf (charCode)) ? 1 : 0; + /* If the character falls within the confines of the BMP, return + 1. */ + if (charCode < 65536) + return paint.hasGlyph (String.valueOf ((char) charCode)) ? 1 : 0; + + /* Otherwise return 0. */ + return 0; } }; diff --git a/java/org/gnu/emacs/EmacsSdk7FontDriver.java b/java/org/gnu/emacs/EmacsSdk7FontDriver.java index b8aecbe7c2d..21ae159d5bd 100644 --- a/java/org/gnu/emacs/EmacsSdk7FontDriver.java +++ b/java/org/gnu/emacs/EmacsSdk7FontDriver.java @@ -291,13 +291,18 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver @Override public int - hasChar (FontSpec font, char charCode) + hasChar (FontSpec font, int charCode) { float missingGlyphWidth, width; Rect rect1, rect2; Paint paint; Sdk7FontObject fontObject; + /* Ignore characters outside the BMP. */ + + if (charCode > 65535) + return 0; + if (font instanceof Sdk7FontObject) { fontObject = (Sdk7FontObject) font; @@ -308,7 +313,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver paint.setTextSize (10); - if (Character.isWhitespace (charCode)) + if (Character.isWhitespace ((char) charCode)) return 1; missingGlyphWidth = paint.measureText (TOFU_STRING); @@ -325,7 +330,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver paint.getTextBounds (TOFU_STRING, 0, TOFU_STRING.length (), rect1); - paint.getTextBounds ("" + charCode, 0, 1, rect2); + paint.getTextBounds ("" + (char) charCode, 0, 1, rect2); return rect1.equals (rect2) ? 0 : 1; } @@ -410,8 +415,11 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver @Override public int - encodeChar (FontObject fontObject, char charCode) + encodeChar (FontObject fontObject, int charCode) { + if (charCode > 65535) + return FONT_INVALID_CODE; + return charCode; } diff --git a/src/androidfont.c b/src/androidfont.c index 1a26741925f..9a1bf5652fc 100644 --- a/src/androidfont.c +++ b/src/androidfont.c @@ -204,11 +204,11 @@ android_init_font_driver (void) FIND_METHOD (open_font, "openFont", "(Lorg/gnu/emacs/EmacsFontDriver$Font" "Entity;I)Lorg/gnu/emacs/EmacsFontDriver$FontObject;"); FIND_METHOD (has_char, "hasChar", "(Lorg/gnu/emacs/EmacsFontDriver$Font" - "Spec;C)I"); + "Spec;I)I"); FIND_METHOD (text_extents, "textExtents", "(Lorg/gnu/emacs/EmacsFontDriver" "$FontObject;[ILorg/gnu/emacs/EmacsFontDriver$FontMetrics;)V"); FIND_METHOD (encode_char, "encodeChar", "(Lorg/gnu/emacs/EmacsFontDriver" - "$FontObject;C)I"); + "$FontObject;I)I"); FIND_METHOD (draw, "draw", "(Lorg/gnu/emacs/EmacsFontDriver$FontObject;" "Lorg/gnu/emacs/EmacsGC;Lorg/gnu/emacs/EmacsDrawable;[IIIIZ)I"); -- 2.39.5