8186317: Cache font layout tables for use by harfbuzz
Reviewed-by: srl, pnarayanan
--- a/jdk/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java Thu Aug 24 11:30:13 2017 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java Mon Aug 28 11:53:44 2017 -0700
@@ -192,7 +192,8 @@
if (font instanceof FileFont) {
pScaler = ((FileFont)font).getScaler().nativeScaler;
}
- shape(font, strike, ptSize, mat, pScaler, pNativeFont, isAAT(font),
+ shape(font, strike, ptSize, mat, pScaler, pNativeFont,
+ layoutTables, isAAT(font),
tr.text, data, key.script(),
tr.start, tr.limit, baseIndex, pt,
typo_flags, gmask);
@@ -210,7 +211,7 @@
/* Native method to invoke harfbuzz layout engine */
private static native boolean
shape(Font2D font, FontStrike strike, float ptSize, float[] mat,
- long pscaler, long pNativeFont, boolean aat,
+ long pscaler, long pNativeFont, long layoutTables, boolean aat,
char[] chars, GVData data,
int script, int offset, int limit,
int baseIndex, Point2D.Float pt, int typo_flags, int slot);
--- a/jdk/src/java.desktop/share/native/common/font/fontscalerdefs.h Thu Aug 24 11:30:13 2017 -0700
+++ b/jdk/src/java.desktop/share/native/common/font/fontscalerdefs.h Mon Aug 28 11:53:44 2017 -0700
@@ -119,6 +119,7 @@
#define GSUB_TAG 0x47535542 /* 'GSUB' */
#define GPOS_TAG 0x47504F53 /* 'GPOS' */
#define GDEF_TAG 0x47444546 /* 'GDEF' */
+#define HEAD_TAG 0x68656164 /* 'head' */
#define MORT_TAG 0x6D6F7274 /* 'mort' */
#define MORX_TAG 0x6D6F7278 /* 'morx' */
#define KERN_TAG 0x6B65726E /* 'kern' */
@@ -126,9 +127,10 @@
typedef struct TTLayoutTableCacheEntry {
const void* ptr;
int len;
+ int tag;
} TTLayoutTableCacheEntry;
-#define LAYOUTCACHE_ENTRIES 6
+#define LAYOUTCACHE_ENTRIES 7
typedef struct TTLayoutTableCache {
TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES];
--- a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c Thu Aug 24 11:30:13 2017 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c Mon Aug 28 11:53:44 2017 -0700
@@ -203,6 +203,7 @@
jfloat ptSize,
jlong pScaler,
jlong pNativeFont,
+ jlong layoutTables,
jfloatArray matrix,
jboolean aat) {
@@ -215,6 +216,7 @@
fi->font2D = font2D;
fi->fontStrike = fontStrike;
fi->nativeFont = pNativeFont;
+ fi->layoutTables = (TTLayoutTableCache*)layoutTables;
fi->aat = aat;
(*env)->GetFloatArrayRegion(env, matrix, 0, 4, fi->matrix);
fi->ptSize = ptSize;
@@ -241,6 +243,7 @@
jfloatArray matrix,
jlong pScaler,
jlong pNativeFont,
+ jlong layoutTables,
jboolean aat,
jcharArray text,
jobject gvdata,
@@ -269,7 +272,7 @@
JDKFontInfo *jdkFontInfo =
createJDKFontInfo(env, font2D, fontStrike, ptSize,
- pScaler, pNativeFont, matrix, aat);
+ pScaler, pNativeFont, layoutTables, matrix, aat);
if (!jdkFontInfo) {
return JNI_FALSE;
}
--- a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc Thu Aug 24 11:30:13 2017 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc Mon Aug 28 11:53:44 2017 -0700
@@ -273,34 +273,63 @@
static void _do_nothing(void) {
}
+static void _free_nothing(void*) {
+}
+
static hb_blob_t *
reference_table(hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) {
JDKFontInfo *jdkFontInfo = (JDKFontInfo*)user_data;
JNIEnv* env = jdkFontInfo->env;
jobject font2D = jdkFontInfo->font2D;
- jsize length;
- jbyte* buffer;
+ jsize length = 0;
+ void* buffer = NULL;
+ int cacheIdx = 0;
// HB_TAG_NONE is 0 and is used to get the whole font file.
- // It is not expected not be needed for JDK.
- if (tag == 0) {
+ // It is not expected to be needed for JDK.
+ if (tag == 0 || jdkFontInfo->layoutTables == NULL) {
return NULL;
}
- jbyteArray tableBytes = (jbyteArray)
- env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag);
- if (tableBytes == NULL) {
- return NULL;
+
+ for (cacheIdx=0; cacheIdx<LAYOUTCACHE_ENTRIES; cacheIdx++) {
+ if (tag == jdkFontInfo->layoutTables->entries[cacheIdx].tag) break;
+ }
+
+ if (cacheIdx < LAYOUTCACHE_ENTRIES) { // if found
+ if (jdkFontInfo->layoutTables->entries[cacheIdx].len != -1) {
+ length = jdkFontInfo->layoutTables->entries[cacheIdx].len;
+ buffer = (void*)jdkFontInfo->layoutTables->entries[cacheIdx].ptr;
+ }
}
- length = env->GetArrayLength(tableBytes);
- buffer = (jbyte *)calloc(length, sizeof(jbyte));
- env->GetByteArrayRegion(tableBytes, 0, length, buffer);
+
+ if (buffer == NULL) {
+ jbyteArray tableBytes = (jbyteArray)
+ env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag);
+ if (tableBytes == NULL) {
+ return NULL;
+ }
+ length = env->GetArrayLength(tableBytes);
+ buffer = calloc(length, sizeof(jbyte));
+ env->GetByteArrayRegion(tableBytes, 0, length, (jbyte*)buffer);
+
+ if (cacheIdx >= LAYOUTCACHE_ENTRIES) { // not a cacheable table
+ return hb_blob_create((const char *)buffer, length,
+ HB_MEMORY_MODE_WRITABLE,
+ buffer, free);
+ } else {
+ jdkFontInfo->layoutTables->entries[cacheIdx].len = length;
+ jdkFontInfo->layoutTables->entries[cacheIdx].ptr = buffer;
+ }
+ }
return hb_blob_create((const char *)buffer, length,
- HB_MEMORY_MODE_WRITABLE,
- buffer, free);
+ HB_MEMORY_MODE_READONLY,
+ NULL, _free_nothing);
}
+
+
hb_face_t*
hb_jdk_face_create(JDKFontInfo *jdkFontInfo,
hb_destroy_func_t destroy) {
--- a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h Thu Aug 24 11:30:13 2017 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h Mon Aug 28 11:53:44 2017 -0700
@@ -29,6 +29,7 @@
#include "hb.h"
#include <jni.h>
#include <sunfontids.h>
+#include <fontscalerdefs.h>
# ifdef __cplusplus
extern "C" {
@@ -39,6 +40,7 @@
jobject font2D;
jobject fontStrike;
long nativeFont;
+ TTLayoutTableCache *layoutTables;
float matrix[4];
float ptSize;
float xPtSize;
--- a/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c Thu Aug 24 11:30:13 2017 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c Mon Aug 28 11:53:44 2017 -0700
@@ -350,6 +350,13 @@
for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
ltc->entries[i].len = -1;
}
+ ltc->entries[0].tag = GDEF_TAG;
+ ltc->entries[1].tag = GPOS_TAG;
+ ltc->entries[2].tag = GSUB_TAG;
+ ltc->entries[3].tag = HEAD_TAG;
+ ltc->entries[4].tag = KERN_TAG;
+ ltc->entries[5].tag = MORT_TAG;
+ ltc->entries[6].tag = MORX_TAG;
}
return ltc;
}