diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java index f8b456b982c50..2896c46b119c2 100644 --- a/graphics/java/android/graphics/fonts/FontFileUtil.java +++ b/graphics/java/android/graphics/fonts/FontFileUtil.java @@ -20,6 +20,8 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import dalvik.annotation.optimization.FastNative; + import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -131,4 +133,44 @@ public class FontFileUtil { buffer.order(originalOrder); } } + + /** + * Analyze head OpenType table and return fontRevision value as 32bit integer. + * + * The font revision is stored in 16.16 bit fixed point value. This function returns this fixed + * point value as 32 bit integer, i.e. the value multiplied with 65536. + * + * IllegalArgumentException will be thrown for invalid font data. + * If the font file is invalid, returns -1L. + * + * @param buffer a buffer of OpenType font + * @param index a font index + * @return font revision that shifted 16 bits left. + */ + public static long getRevision(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index) { + return nGetFontRevision(buffer, index); + } + + /** + * Analyze name OpenType table and return PostScript name. + * + * IllegalArgumentException will be thrown for invalid font data. + * null will be returned if not found or the PostScript name is invalid. + * + * @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 String getPostScriptName(@NonNull ByteBuffer buffer, + @IntRange(from = 0) int index) { + return nGetFontPostScriptName(buffer, index); + } + + @FastNative + private static native long nGetFontRevision(@NonNull ByteBuffer buffer, + @IntRange(from = 0) int index); + + @FastNative + private static native String nGetFontPostScriptName(@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 f612bce748ff1..943423f658825 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -233,6 +234,51 @@ static jlong FontBufferHelper_getReleaseFunc(CRITICAL_JNI_PARAMS) { /////////////////////////////////////////////////////////////////////////////// +// Fast Native +static jlong FontFileUtil_getFontRevision(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 0; + } + jlong fontSize = env->GetDirectBufferCapacity(buffer); + if (fontSize <= 0) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "buffer size must not be zero or negative"); + return 0; + } + minikin::FontFileParser parser(fontPtr, fontSize, index); + std::optional revision = parser.getFontRevision(); + if (!revision.has_value()) { + return -1L; + } + return revision.value(); +} + +static jstring FontFileUtil_getFontPostScriptName(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 nullptr; + } + jlong fontSize = env->GetDirectBufferCapacity(buffer); + if (fontSize <= 0) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "buffer size must not be zero or negative"); + return nullptr; + } + minikin::FontFileParser parser(fontPtr, fontSize, index); + std::optional psName = parser.getPostScriptName(); + if (!psName.has_value()) { + return nullptr; // null + } + return env->NewStringUTF(psName->c_str()); +} +/////////////////////////////////////////////////////////////////////////////// + static const JNINativeMethod gFontBuilderMethods[] = { { "nInitBuilder", "()J", (void*) Font_Builder_initBuilder }, { "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis }, @@ -254,13 +300,21 @@ static const JNINativeMethod gFontBufferHelperMethods[] = { { "nGetReleaseFunc", "()J", (void*) FontBufferHelper_getReleaseFunc }, }; +static const JNINativeMethod gFontFileUtilMethods[] = { + { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision }, + { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;", + (void*) FontFileUtil_getFontPostScriptName }, +}; + int register_android_graphics_fonts_Font(JNIEnv* env) { return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods, NELEM(gFontBuilderMethods)) + RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods, NELEM(gFontMethods)) + RegisterMethodsOrDie(env, "android/graphics/fonts/NativeFontBufferHelper", - gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods)); + gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods)) + + RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods, + NELEM(gFontFileUtilMethods)); } namespace fonts {