diff --git a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java index 1771671db26a0..52cc4cac48168 100644 --- a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java +++ b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java @@ -17,11 +17,15 @@ package android.graphics; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; import android.content.Context; import android.content.res.AssetManager; +import android.graphics.fonts.Font; import android.graphics.fonts.FontFileUtil; import android.graphics.fonts.FontVariationAxis; +import android.graphics.fonts.SystemFonts; import android.util.Log; import android.util.Pair; @@ -144,4 +148,18 @@ public class FontFileUtilTest { assertEquals(path + "#" + axes, italic, FontFileUtil.unpackItalic(packed)); } } + + @Test + public void testExtension() throws IOException { + for (Font f : SystemFonts.getAvailableFonts()) { + String name = f.getFile().getName(); + if (!name.endsWith(".ttf") && !name.endsWith(".otf")) { + continue; // Only test ttf/otf file + } + int isOtfFile = FontFileUtil.isPostScriptType1Font(f.getBuffer(), 0); + assertNotEquals(-1, isOtfFile); + String extension = isOtfFile == 1 ? ".otf" : ".ttf"; + assertTrue(name.endsWith(extension)); + } + } } diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java index 2896c46b119c2..af49619fb8405 100644 --- a/graphics/java/android/graphics/fonts/FontFileUtil.java +++ b/graphics/java/android/graphics/fonts/FontFileUtil.java @@ -166,6 +166,23 @@ public class FontFileUtil { return nGetFontPostScriptName(buffer, index); } + /** + * Analyze name OpenType table and return true if the font has PostScript Type 1 glyphs. + * + * IllegalArgumentException will be thrown for invalid font data. + * -1 will be returned if the byte buffer is not a OpenType font data. + * 0 will be returned if the font file doesn't have PostScript Type 1 glyphs, i.e. ttf file. + * 1 will be returned if the font file has PostScript Type 1 glyphs, i.e. otf file. + * + * @param buffer a buffer of OpenType font + * @param index a font index + * @return a post script name or null if it is invalid or not found. + */ + public static int isPostScriptType1Font(@NonNull ByteBuffer buffer, + @IntRange(from = 0) int index) { + return nIsPostScriptType1Font(buffer, index); + } + @FastNative private static native long nGetFontRevision(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index); @@ -173,4 +190,8 @@ public class FontFileUtil { @FastNative private static native String nGetFontPostScriptName(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index); + + @FastNative + private static native int nIsPostScriptType1Font(@NonNull ByteBuffer buffer, + @IntRange(from = 0) int index); } diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp index 943423f658825..b944310d88222 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -277,6 +277,28 @@ static jstring FontFileUtil_getFontPostScriptName(JNIEnv* env, jobject, jobject } return env->NewStringUTF(psName->c_str()); } + +static jint FontFileUtil_isPostScriptType1Font(JNIEnv* env, jobject, jobject buffer, jint index) { + NPE_CHECK_RETURN_ZERO(env, buffer); + const void* fontPtr = env->GetDirectBufferAddress(buffer); + if (fontPtr == nullptr) { + jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer"); + return -1; + } + jlong fontSize = env->GetDirectBufferCapacity(buffer); + if (fontSize <= 0) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "buffer size must not be zero or negative"); + return -1; + } + minikin::FontFileParser parser(fontPtr, fontSize, index); + std::optional isType1 = parser.isPostScriptType1Font(); + if (!isType1.has_value()) { + return -1; // not an OpenType font. HarfBuzz failed to parse it. + } + return isType1.value(); +} + /////////////////////////////////////////////////////////////////////////////// static const JNINativeMethod gFontBuilderMethods[] = { @@ -304,6 +326,8 @@ static const JNINativeMethod gFontFileUtilMethods[] = { { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision }, { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;", (void*) FontFileUtil_getFontPostScriptName }, + { "nIsPostScriptType1Font", "(Ljava/nio/ByteBuffer;I)I", + (void*) FontFileUtil_isPostScriptType1Font }, }; int register_android_graphics_fonts_Font(JNIEnv* env) {