1 #include "hb.h" 2 #include "hb-jdk.h" 3 #ifdef MACOSX 4 #include "hb-coretext.h" 5 #endif 6 #include <stdlib.h> 7 8 #if defined(__GNUC__) && __GNUC__ >= 4 9 #define HB_UNUSED __attribute__((unused)) 10 #else 11 #define HB_UNUSED 12 #endif 13 14 static hb_bool_t 15 hb_jdk_get_glyph (hb_font_t *font HB_UNUSED, 16 void *font_data, 17 hb_codepoint_t unicode, 18 hb_codepoint_t variation_selector, 19 hb_codepoint_t *glyph, 20 void *user_data HB_UNUSED) 21 { 22 23 JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; 24 JNIEnv* env = jdkFontInfo->env; 25 jobject font2D = jdkFontInfo->font2D; 26 hb_codepoint_t u = (variation_selector==0) ? unicode : variation_selector; 27 28 *glyph = (hb_codepoint_t) 29 env->CallIntMethod(font2D, sunFontIDs.f2dCharToGlyphMID, u); 30 return (*glyph != 0); 31 } 32 33 // This is also define in freetypescaler.c and similar macros are 34 // in fontscalerdefs.h. Consider tidying this up. 35 #define FloatToF26Dot6(x) ((unsigned int) ((x)*64)) 36 37 static hb_position_t 38 hb_jdk_get_glyph_h_advance (hb_font_t *font HB_UNUSED, 39 void *font_data, 40 hb_codepoint_t glyph, 41 void *user_data HB_UNUSED) 42 { 43 44 float fadv = 0.0f; 45 if ((glyph & 0xfffe) == 0xfffe) { 46 return 0; // JDK uses this glyph code. 47 } 48 49 JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; 50 JNIEnv* env = jdkFontInfo->env; 51 jobject fontStrike = jdkFontInfo->fontStrike; 52 jobject pt = env->CallObjectMethod(fontStrike, 53 sunFontIDs.getGlyphMetricsMID, glyph); 54 55 if (pt == NULL) { 56 return 0; 57 } 58 fadv = env->GetFloatField(pt, sunFontIDs.xFID); 59 env->DeleteLocalRef(pt); 60 61 return FloatToF26Dot6(fadv); // should this round ? 62 } 63 64 static hb_position_t 65 hb_jdk_get_glyph_v_advance (hb_font_t *font HB_UNUSED, 66 void *font_data, 67 hb_codepoint_t glyph, 68 void *user_data HB_UNUSED) 69 { 70 71 float fadv = 0.0f; 72 if ((glyph & 0xfffe) == 0xfffe) { 73 return 0; // JDK uses this glyph code. 74 } 75 76 JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; 77 JNIEnv* env = jdkFontInfo->env; 78 jobject fontStrike = jdkFontInfo->fontStrike; 79 jobject pt = env->CallObjectMethod(fontStrike, 80 sunFontIDs.getGlyphMetricsMID, glyph); 81 82 if (pt == NULL) { 83 return 0; 84 } 85 fadv = env->GetFloatField(pt, sunFontIDs.yFID); 86 env->DeleteLocalRef(pt); 87 88 return FloatToF26Dot6(fadv); // should this round ? 89 90 } 91 92 static hb_bool_t 93 hb_jdk_get_glyph_h_origin (hb_font_t *font HB_UNUSED, 94 void *font_data HB_UNUSED, 95 hb_codepoint_t glyph HB_UNUSED, 96 hb_position_t *x HB_UNUSED, 97 hb_position_t *y HB_UNUSED, 98 void *user_data HB_UNUSED) 99 { 100 /* We always work in the horizontal coordinates. */ 101 return true; 102 } 103 104 static hb_bool_t 105 hb_jdk_get_glyph_v_origin (hb_font_t *font HB_UNUSED, 106 void *font_data, 107 hb_codepoint_t glyph, 108 hb_position_t *x, 109 hb_position_t *y, 110 void *user_data HB_UNUSED) 111 { 112 return false; 113 } 114 115 static hb_position_t 116 hb_jdk_get_glyph_h_kerning (hb_font_t *font, 117 void *font_data, 118 hb_codepoint_t lejdk_glyph, 119 hb_codepoint_t right_glyph, 120 void *user_data HB_UNUSED) 121 { 122 /* Not implemented. This seems to be in the HB API 123 * as a way to fall back to Freetype's kerning support 124 * which be could based on some on-the fly glyph analysis. 125 * But more likely it reads the kern table. That is easy 126 * enough code to add if we find a need to fall back 127 * to that instead of using gpos. It seems like if 128 * there is a gpos table at all, the practice is to 129 * use that and ignore kern, no matter that gpos does 130 * not implement the kern feature. 131 */ 132 return 0; 133 } 134 135 static hb_position_t 136 hb_jdk_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, 137 void *font_data HB_UNUSED, 138 hb_codepoint_t top_glyph HB_UNUSED, 139 hb_codepoint_t bottom_glyph HB_UNUSED, 140 void *user_data HB_UNUSED) 141 { 142 /* OpenType doesn't have vertical-kerning other than GPOS. */ 143 return 0; 144 } 145 146 static hb_bool_t 147 hb_jdk_get_glyph_extents (hb_font_t *font HB_UNUSED, 148 void *font_data, 149 hb_codepoint_t glyph, 150 hb_glyph_extents_t *extents, 151 void *user_data HB_UNUSED) 152 { 153 /* TODO */ 154 return false; 155 } 156 157 static hb_bool_t 158 hb_jdk_get_glyph_contour_point (hb_font_t *font HB_UNUSED, 159 void *font_data, 160 hb_codepoint_t glyph, 161 unsigned int point_index, 162 hb_position_t *x, 163 hb_position_t *y, 164 void *user_data HB_UNUSED) 165 { 166 if ((glyph & 0xfffe) == 0xfffe) { 167 *x = 0; *y = 0; 168 return true; 169 } 170 171 JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data; 172 JNIEnv* env = jdkFontInfo->env; 173 jobject fontStrike = jdkFontInfo->fontStrike; 174 jobject pt = env->CallObjectMethod(fontStrike, 175 sunFontIDs.getGlyphPointMID, 176 glyph, point_index); 177 178 if (pt == NULL) { 179 *x = 0; *y = 0; 180 return true; 181 } 182 *x = FloatToF26Dot6(env->GetFloatField(pt, sunFontIDs.xFID)); 183 *y = FloatToF26Dot6(env->GetFloatField(pt, sunFontIDs.yFID)); 184 env->DeleteLocalRef(pt); 185 186 return true; 187 } 188 189 static hb_bool_t 190 hb_jdk_get_glyph_name (hb_font_t *font HB_UNUSED, 191 void *font_data, 192 hb_codepoint_t glyph, 193 char *name, unsigned int size, 194 void *user_data HB_UNUSED) 195 { 196 return false; 197 } 198 199 static hb_bool_t 200 hb_jdk_get_glyph_from_name (hb_font_t *font HB_UNUSED, 201 void *font_data, 202 const char *name, int len, 203 hb_codepoint_t *glyph, 204 void *user_data HB_UNUSED) 205 { 206 return false; 207 } 208 209 // remind : can we initialise this from the code we call 210 // from the class static method in Java to make it 211 // completely thread safe. 212 static hb_font_funcs_t * 213 _hb_jdk_get_font_funcs (void) 214 { 215 static hb_font_funcs_t *jdk_ffuncs = NULL; 216 hb_font_funcs_t *ff; 217 218 if (!jdk_ffuncs) { 219 ff = hb_font_funcs_create(); 220 221 hb_font_funcs_set_glyph_func(ff, hb_jdk_get_glyph, NULL, NULL); 222 hb_font_funcs_set_glyph_h_advance_func(ff, 223 hb_jdk_get_glyph_h_advance, NULL, NULL); 224 hb_font_funcs_set_glyph_v_advance_func(ff, 225 hb_jdk_get_glyph_v_advance, NULL, NULL); 226 hb_font_funcs_set_glyph_h_origin_func(ff, 227 hb_jdk_get_glyph_h_origin, NULL, NULL); 228 hb_font_funcs_set_glyph_v_origin_func(ff, 229 hb_jdk_get_glyph_v_origin, NULL, NULL); 230 hb_font_funcs_set_glyph_h_kerning_func(ff, 231 hb_jdk_get_glyph_h_kerning, NULL, NULL); 232 hb_font_funcs_set_glyph_v_kerning_func(ff, 233 hb_jdk_get_glyph_v_kerning, NULL, NULL); 234 hb_font_funcs_set_glyph_extents_func(ff, 235 hb_jdk_get_glyph_extents, NULL, NULL); 236 hb_font_funcs_set_glyph_contour_point_func(ff, 237 hb_jdk_get_glyph_contour_point, NULL, NULL); 238 hb_font_funcs_set_glyph_name_func(ff, 239 hb_jdk_get_glyph_name, NULL, NULL); 240 hb_font_funcs_set_glyph_from_name_func(ff, 241 hb_jdk_get_glyph_from_name, NULL, NULL); 242 hb_font_funcs_make_immutable(ff); // done setting functions. 243 jdk_ffuncs = ff; 244 } 245 return jdk_ffuncs; 246 } 247 248 static void _do_nothing(void) { 249 } 250 251 static hb_blob_t * 252 reference_table(hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) { 253 254 JDKFontInfo *jdkFontInfo = (JDKFontInfo*)user_data; 255 JNIEnv* env = jdkFontInfo->env; 256 jobject font2D = jdkFontInfo->font2D; 257 jsize length; 258 jbyte* buffer; 259 260 // HB_TAG_NONE is 0 and is used to get the whole font file. 261 // It is not expected not be needed for JDK. 262 if (tag == 0) { 263 return NULL; 264 } 265 jbyteArray tableBytes = (jbyteArray) 266 env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag); 267 if (tableBytes == NULL) { 268 return NULL; 269 } 270 length = env->GetArrayLength(tableBytes); 271 buffer = new jbyte[length]; 272 env->GetByteArrayRegion(tableBytes, 0, length, buffer); 273 274 return hb_blob_create((const char *)buffer, length, 275 HB_MEMORY_MODE_WRITABLE, 276 buffer, free); 277 } 278 279 hb_face_t* 280 hb_jdk_face_create(JDKFontInfo *jdkFontInfo, 281 hb_destroy_func_t destroy) { 282 283 hb_face_t *face = 284 hb_face_create_for_tables(reference_table, jdkFontInfo, destroy); 285 286 return face; 287 } 288 289 static hb_font_t* _hb_jdk_font_create(JDKFontInfo *jdkFontInfo, 290 hb_destroy_func_t destroy) { 291 292 hb_font_t *font; 293 hb_face_t *face; 294 295 face = hb_jdk_face_create(jdkFontInfo, destroy); 296 font = hb_font_create(face); 297 hb_face_destroy (face); 298 hb_font_set_funcs (font, 299 _hb_jdk_get_font_funcs (), 300 jdkFontInfo, (hb_destroy_func_t) _do_nothing); 301 hb_font_set_scale (font, 302 FloatToF26Dot6(jdkFontInfo->xPtSize), 303 FloatToF26Dot6(jdkFontInfo->yPtSize)); 304 return font; 305 } 306 307 #ifdef MACOSX 308 static hb_font_t* _hb_jdk_ct_font_create(JDKFontInfo *jdkFontInfo) { 309 310 hb_font_t *font = NULL; 311 hb_face_t *face = NULL; 312 if (jdkFontInfo->nativeFont == 0) { 313 return NULL; 314 } 315 face = hb_coretext_face_create((CGFontRef)(jdkFontInfo->nativeFont)); 316 font = hb_font_create(face); 317 hb_face_destroy(face); 318 hb_font_set_scale(font, 319 FloatToF26Dot6(jdkFontInfo->xPtSize), 320 FloatToF26Dot6(jdkFontInfo->yPtSize)); 321 return font; 322 } 323 #endif 324 325 hb_font_t* hb_jdk_font_create(JDKFontInfo *jdkFontInfo, 326 hb_destroy_func_t destroy) { 327 328 hb_font_t* font = NULL; 329 330 #ifdef MACOSX 331 if (jdkFontInfo->aat) { 332 font = _hb_jdk_ct_font_create(jdkFontInfo); 333 } 334 #endif 335 if (font == NULL) { 336 font = _hb_jdk_font_create(jdkFontInfo, destroy); 337 } 338 return font; 339 }