8186317: Cache font layout tables for use by harfbuzz

Reviewed-by: srl, pnarayanan
This commit is contained in:
Phil Race 2017-08-28 11:53:44 -07:00
parent 05aa9c6d1d
commit 4211e523ea
6 changed files with 61 additions and 17 deletions

View File

@ -192,7 +192,8 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
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 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
/* 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);

View File

@ -119,6 +119,7 @@ typedef struct GlyphInfo {
#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 GlyphInfo {
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];

View File

@ -203,6 +203,7 @@ JDKFontInfo*
jfloat ptSize,
jlong pScaler,
jlong pNativeFont,
jlong layoutTables,
jfloatArray matrix,
jboolean aat) {
@ -215,6 +216,7 @@ JDKFontInfo*
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 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape
jfloatArray matrix,
jlong pScaler,
jlong pNativeFont,
jlong layoutTables,
jboolean aat,
jcharArray text,
jobject gvdata,
@ -269,7 +272,7 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape
JDKFontInfo *jdkFontInfo =
createJDKFontInfo(env, font2D, fontStrike, ptSize,
pScaler, pNativeFont, matrix, aat);
pScaler, pNativeFont, layoutTables, matrix, aat);
if (!jdkFontInfo) {
return JNI_FALSE;
}

View File

@ -273,34 +273,63 @@ _hb_jdk_get_font_funcs (void)
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;
}
}
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;
}
}
length = env->GetArrayLength(tableBytes);
buffer = (jbyte *)calloc(length, sizeof(jbyte));
env->GetByteArrayRegion(tableBytes, 0, length, 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) {

View File

@ -29,6 +29,7 @@
#include "hb.h"
#include <jni.h>
#include <sunfontids.h>
#include <fontscalerdefs.h>
# ifdef __cplusplus
extern "C" {
@ -39,6 +40,7 @@ typedef struct JDKFontInfo_Struct {
jobject font2D;
jobject fontStrike;
long nativeFont;
TTLayoutTableCache *layoutTables;
float matrix[4];
float ptSize;
float xPtSize;

View File

@ -350,6 +350,13 @@ JNIEXPORT TTLayoutTableCache* newLayoutTableCache() {
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;
}