--- /dev/null 2015-11-17 15:39:41.000000000 -0800 +++ new/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc 2015-11-17 15:39:41.000000000 -0800 @@ -0,0 +1,339 @@ +#include "hb.h" +#include "hb-jdk.h" +#ifdef MACOSX +#include "hb-coretext.h" +#endif +#include + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define HB_UNUSED __attribute__((unused)) +#else +#define HB_UNUSED +#endif + +static hb_bool_t +hb_jdk_get_glyph (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + + JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; + JNIEnv* env = jdkFontInfo->env; + jobject font2D = jdkFontInfo->font2D; + hb_codepoint_t u = (variation_selector==0) ? unicode : variation_selector; + + *glyph = (hb_codepoint_t) + env->CallIntMethod(font2D, sunFontIDs.f2dCharToGlyphMID, u); + return (*glyph != 0); +} + +// This is also define in freetypescaler.c and similar macros are +// in fontscalerdefs.h. Consider tidying this up. +#define FloatToF26Dot6(x) ((unsigned int) ((x)*64)) + +static hb_position_t +hb_jdk_get_glyph_h_advance (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + + float fadv = 0.0f; + if ((glyph & 0xfffe) == 0xfffe) { + return 0; // JDK uses this glyph code. + } + + JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; + JNIEnv* env = jdkFontInfo->env; + jobject fontStrike = jdkFontInfo->fontStrike; + jobject pt = env->CallObjectMethod(fontStrike, + sunFontIDs.getGlyphMetricsMID, glyph); + + if (pt == NULL) { + return 0; + } + fadv = env->GetFloatField(pt, sunFontIDs.xFID); + env->DeleteLocalRef(pt); + + return FloatToF26Dot6(fadv); // should this round ? +} + +static hb_position_t +hb_jdk_get_glyph_v_advance (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + + float fadv = 0.0f; + if ((glyph & 0xfffe) == 0xfffe) { + return 0; // JDK uses this glyph code. + } + + JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; + JNIEnv* env = jdkFontInfo->env; + jobject fontStrike = jdkFontInfo->fontStrike; + jobject pt = env->CallObjectMethod(fontStrike, + sunFontIDs.getGlyphMetricsMID, glyph); + + if (pt == NULL) { + return 0; + } + fadv = env->GetFloatField(pt, sunFontIDs.yFID); + env->DeleteLocalRef(pt); + + return FloatToF26Dot6(fadv); // should this round ? + +} + +static hb_bool_t +hb_jdk_get_glyph_h_origin (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph HB_UNUSED, + hb_position_t *x HB_UNUSED, + hb_position_t *y HB_UNUSED, + void *user_data HB_UNUSED) +{ + /* We always work in the horizontal coordinates. */ + return true; +} + +static hb_bool_t +hb_jdk_get_glyph_v_origin (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + return false; +} + +static hb_position_t +hb_jdk_get_glyph_h_kerning (hb_font_t *font, + void *font_data, + hb_codepoint_t lejdk_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) +{ + /* Not implemented. This seems to be in the HB API + * as a way to fall back to Freetype's kerning support + * which be could based on some on-the fly glyph analysis. + * But more likely it reads the kern table. That is easy + * enough code to add if we find a need to fall back + * to that instead of using gpos. It seems like if + * there is a gpos table at all, the practice is to + * use that and ignore kern, no matter that gpos does + * not implement the kern feature. + */ + return 0; +} + +static hb_position_t +hb_jdk_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph HB_UNUSED, + hb_codepoint_t bottom_glyph HB_UNUSED, + void *user_data HB_UNUSED) +{ + /* OpenType doesn't have vertical-kerning other than GPOS. */ + return 0; +} + +static hb_bool_t +hb_jdk_get_glyph_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) +{ + /* TODO */ + return false; +} + +static hb_bool_t +hb_jdk_get_glyph_contour_point (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + unsigned int point_index, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + if ((glyph & 0xfffe) == 0xfffe) { + *x = 0; *y = 0; + return true; + } + + JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; + JNIEnv* env = jdkFontInfo->env; + jobject fontStrike = jdkFontInfo->fontStrike; + jobject pt = env->CallObjectMethod(fontStrike, + sunFontIDs.getGlyphPointMID, + glyph, point_index); + + if (pt == NULL) { + *x = 0; *y = 0; + return true; + } + *x = FloatToF26Dot6(env->GetFloatField(pt, sunFontIDs.xFID)); + *y = FloatToF26Dot6(env->GetFloatField(pt, sunFontIDs.yFID)); + env->DeleteLocalRef(pt); + + return true; +} + +static hb_bool_t +hb_jdk_get_glyph_name (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) +{ + return false; +} + +static hb_bool_t +hb_jdk_get_glyph_from_name (hb_font_t *font HB_UNUSED, + void *font_data, + const char *name, int len, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + return false; +} + +// remind : can we initialise this from the code we call +// from the class static method in Java to make it +// completely thread safe. +static hb_font_funcs_t * +_hb_jdk_get_font_funcs (void) +{ + static hb_font_funcs_t *jdk_ffuncs = NULL; + hb_font_funcs_t *ff; + + if (!jdk_ffuncs) { + ff = hb_font_funcs_create(); + + hb_font_funcs_set_glyph_func(ff, hb_jdk_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func(ff, + hb_jdk_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func(ff, + hb_jdk_get_glyph_v_advance, NULL, NULL); + hb_font_funcs_set_glyph_h_origin_func(ff, + hb_jdk_get_glyph_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func(ff, + hb_jdk_get_glyph_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func(ff, + hb_jdk_get_glyph_h_kerning, NULL, NULL); + hb_font_funcs_set_glyph_v_kerning_func(ff, + hb_jdk_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func(ff, + hb_jdk_get_glyph_extents, NULL, NULL); + hb_font_funcs_set_glyph_contour_point_func(ff, + hb_jdk_get_glyph_contour_point, NULL, NULL); + hb_font_funcs_set_glyph_name_func(ff, + hb_jdk_get_glyph_name, NULL, NULL); + hb_font_funcs_set_glyph_from_name_func(ff, + hb_jdk_get_glyph_from_name, NULL, NULL); + hb_font_funcs_make_immutable(ff); // done setting functions. + jdk_ffuncs = ff; + } + return jdk_ffuncs; +} + +static void _do_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; + + // 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) { + return NULL; + } + jbyteArray tableBytes = (jbyteArray) + env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag); + if (tableBytes == NULL) { + return NULL; + } + length = env->GetArrayLength(tableBytes); + buffer = new jbyte[length]; + env->GetByteArrayRegion(tableBytes, 0, length, buffer); + + return hb_blob_create((const char *)buffer, length, + HB_MEMORY_MODE_WRITABLE, + buffer, free); +} + +hb_face_t* +hb_jdk_face_create(JDKFontInfo *jdkFontInfo, + hb_destroy_func_t destroy) { + + hb_face_t *face = + hb_face_create_for_tables(reference_table, jdkFontInfo, destroy); + + return face; +} + +static hb_font_t* _hb_jdk_font_create(JDKFontInfo *jdkFontInfo, + hb_destroy_func_t destroy) { + + hb_font_t *font; + hb_face_t *face; + + face = hb_jdk_face_create(jdkFontInfo, destroy); + font = hb_font_create(face); + hb_face_destroy (face); + hb_font_set_funcs (font, + _hb_jdk_get_font_funcs (), + jdkFontInfo, (hb_destroy_func_t) _do_nothing); + hb_font_set_scale (font, + FloatToF26Dot6(jdkFontInfo->xPtSize), + FloatToF26Dot6(jdkFontInfo->yPtSize)); + return font; +} + +#ifdef MACOSX +static hb_font_t* _hb_jdk_ct_font_create(JDKFontInfo *jdkFontInfo) { + + hb_font_t *font = NULL; + hb_face_t *face = NULL; + if (jdkFontInfo->nativeFont == 0) { + return NULL; + } + face = hb_coretext_face_create((CGFontRef)(jdkFontInfo->nativeFont)); + font = hb_font_create(face); + hb_face_destroy(face); + hb_font_set_scale(font, + FloatToF26Dot6(jdkFontInfo->xPtSize), + FloatToF26Dot6(jdkFontInfo->yPtSize)); + return font; +} +#endif + +hb_font_t* hb_jdk_font_create(JDKFontInfo *jdkFontInfo, + hb_destroy_func_t destroy) { + + hb_font_t* font = NULL; + +#ifdef MACOSX + if (jdkFontInfo->aat) { + font = _hb_jdk_ct_font_create(jdkFontInfo); + } +#endif + if (font == NULL) { + font = _hb_jdk_font_create(jdkFontInfo, destroy); + } + return font; +}