8186317: Cache font layout tables for use by harfbuzz
authorprr
Mon, 28 Aug 2017 11:53:44 -0700
changeset 47188 0048f025c993
parent 47187 ea6212ea3397
child 47189 b119a24038a8
8186317: Cache font layout tables for use by harfbuzz Reviewed-by: srl, pnarayanan
jdk/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java
jdk/src/java.desktop/share/native/common/font/fontscalerdefs.h
jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c
jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc
jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h
jdk/src/java.desktop/share/native/libfontmanager/sunFont.c
--- 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;
 }