1 /* 2 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 #include "stdlib.h" 27 #include "malloc.h" 28 #include "string.h" 29 #include "gdefs.h" 30 #include "jlong.h" 31 #include "sunfontids.h" 32 #include "fontscalerdefs.h" 33 #include "sun_font_FontManager.h" 34 #include "sun_font_NullFontScaler.h" 35 #include "sun_font_StrikeCache.h" 36 37 static void *theNullScalerContext = NULL; 38 extern void AccelGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph); 39 40 41 JNIEXPORT jlong JNICALL 42 Java_sun_font_NullFontScaler_getNullScalerContext 43 (JNIEnv *env, jclass scalerClass) { 44 45 if (theNullScalerContext == NULL) { 46 theNullScalerContext = malloc(1); 47 } 48 return ptr_to_jlong(theNullScalerContext); 49 } 50 51 int isNullScalerContext(void *context) { 52 return theNullScalerContext == context; 53 } 54 55 /* Eventually we may rework it to be a singleton. 56 * This will require additional checks in freeLongMemory/freeIntMemory 57 * and on other hand malformed fonts (main source of null glyph images) 58 * are supposed to be collected fast. 59 * But perhaps it is still right thing to do. 60 * Even better is to eliminate the need to have this native method 61 * but for this it is necessary to rework Strike and drawing logic 62 * to be able to live with NULL pointers without performance hit. 63 */ 64 JNIEXPORT jlong JNICALL Java_sun_font_NullFontScaler_getGlyphImage 65 (JNIEnv *env, jobject scaler, jlong pContext, jint glyphCode) { 66 void *nullscaler = calloc(sizeof(GlyphInfo), 1); 67 return ptr_to_jlong(nullscaler); 68 } 69 70 71 72 void initLCDGammaTables(); 73 74 /* 75 * Class: sun_font_FontManager 76 * Method: getPlatformFontVar 77 * Signature: ()Z 78 */ 79 JNIEXPORT jboolean JNICALL 80 Java_sun_font_FontManager_getPlatformFontVar(JNIEnv *env, jclass cl) { 81 char *c = getenv("JAVA2D_USEPLATFORMFONT"); 82 if (c) { 83 return JNI_TRUE; 84 } else { 85 return JNI_FALSE; 86 } 87 } 88 89 /* placeholder for extern variable */ 90 FontManagerNativeIDs sunFontIDs; 91 92 JNIEXPORT void JNICALL 93 Java_sun_font_FontManager_initIDs 94 (JNIEnv *env, jclass cls) { 95 96 jclass tmpClass = (*env)->FindClass(env, "java/awt/Font"); 97 98 sunFontIDs.getFont2DMID = 99 (*env)->GetMethodID(env, tmpClass, "getFont2D", 100 "()Lsun/font/Font2D;"); 101 sunFontIDs.font2DHandle = 102 (*env)->GetFieldID(env, tmpClass, 103 "font2DHandle", "Lsun/font/Font2DHandle;"); 104 105 sunFontIDs.createdFont = 106 (*env)->GetFieldID(env, tmpClass, "createdFont", "Z"); 107 108 tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont"); 109 sunFontIDs.ttReadBlockMID = 110 (*env)->GetMethodID(env, tmpClass, "readBlock", 111 "(Ljava/nio/ByteBuffer;II)I"); 112 sunFontIDs.ttReadBytesMID = 113 (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B"); 114 115 tmpClass = (*env)->FindClass(env, "sun/font/Type1Font"); 116 sunFontIDs.readFileMID = 117 (*env)->GetMethodID(env, tmpClass, 118 "readFile", "(Ljava/nio/ByteBuffer;)V"); 119 120 tmpClass = (*env)->FindClass(env, "java/awt/geom/Point2D$Float"); 121 sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 122 sunFontIDs.pt2DFloatCtr = 123 (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V"); 124 125 sunFontIDs.xFID = 126 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F"); 127 sunFontIDs.yFID = 128 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F"); 129 130 tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics"); 131 sunFontIDs.strikeMetricsClass=(jclass)(*env)->NewGlobalRef(env, tmpClass); 132 133 sunFontIDs.strikeMetricsCtr = 134 (*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass, 135 "<init>", "(FFFFFFFFFF)V"); 136 137 tmpClass = (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float"); 138 sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 139 sunFontIDs.rect2DFloatCtr = 140 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V"); 141 sunFontIDs.rect2DFloatCtr4 = 142 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, 143 "<init>", "(FFFF)V"); 144 sunFontIDs.rectF2DX = 145 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F"); 146 sunFontIDs.rectF2DY = 147 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F"); 148 sunFontIDs.rectF2DWidth = 149 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F"); 150 sunFontIDs.rectF2DHeight = 151 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F"); 152 153 tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath"); 154 sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 155 sunFontIDs.gpCtr = 156 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V"); 157 sunFontIDs.gpCtrEmpty = 158 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V"); 159 160 tmpClass = (*env)->FindClass(env, "sun/font/Font2D"); 161 sunFontIDs.f2dCharToGlyphMID = 162 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"); 163 sunFontIDs.getMapperMID = 164 (*env)->GetMethodID(env, tmpClass, "getMapper", 165 "()Lsun/font/CharToGlyphMapper;"); 166 sunFontIDs.getTableBytesMID = 167 (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B"); 168 sunFontIDs.canDisplayMID = 169 (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z"); 170 171 tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper"); 172 sunFontIDs.charToGlyphMID = 173 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"); 174 175 tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike"); 176 sunFontIDs.getGlyphMetricsMID = 177 (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics", 178 "(I)Ljava/awt/geom/Point2D$Float;"); 179 sunFontIDs.getGlyphPointMID = 180 (*env)->GetMethodID(env, tmpClass, "getGlyphPoint", 181 "(II)Ljava/awt/geom/Point2D$Float;"); 182 sunFontIDs.adjustPointMID = 183 (*env)->GetMethodID(env, tmpClass, "adjustPoint", 184 "(Ljava/awt/geom/Point2D$Float;)V"); 185 sunFontIDs.pScalerContextFID = 186 (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J"); 187 188 tmpClass = (*env)->FindClass(env, "sun/font/GlyphList"); 189 sunFontIDs.glyphListX = (*env)->GetFieldID(env, tmpClass, "x", "F"); 190 sunFontIDs.glyphListY = (*env)->GetFieldID(env, tmpClass, "y", "F"); 191 sunFontIDs.glyphListLen = (*env)->GetFieldID(env, tmpClass, "len", "I"); 192 sunFontIDs.glyphImages = 193 (*env)->GetFieldID(env, tmpClass, "images", "[J"); 194 sunFontIDs.glyphListUsePos = 195 (*env)->GetFieldID(env, tmpClass, "usePositions", "Z"); 196 sunFontIDs.glyphListPos = 197 (*env)->GetFieldID(env, tmpClass, "positions", "[F"); 198 sunFontIDs.lcdRGBOrder = 199 (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z"); 200 sunFontIDs.lcdSubPixPos = 201 (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z"); 202 203 initLCDGammaTables(); 204 } 205 206 JNIEXPORT FontManagerNativeIDs getSunFontIDs() { 207 return sunFontIDs; 208 } 209 210 JNIEXPORT jobject JNICALL 211 Java_sun_font_FontManager_getFont2D( 212 JNIEnv *env, 213 jclass clsFM, 214 jobject javaFont) { 215 216 return (*env)->CallObjectMethod(env, javaFont, sunFontIDs.getFont2DMID); 217 } 218 219 JNIEXPORT void JNICALL 220 Java_sun_font_FontManager_setFont2D( 221 JNIEnv *env, 222 jclass clsFM, 223 jobject javaFont, 224 jobject fontHandle) { 225 (*env)->SetObjectField(env, javaFont, sunFontIDs.font2DHandle, fontHandle); 226 } 227 228 JNIEXPORT void JNICALL 229 Java_sun_font_FontManager_setCreatedFont( 230 JNIEnv *env, 231 jclass clsFM, 232 jobject javaFont) { 233 (*env)->SetBooleanField(env, javaFont, sunFontIDs.createdFont, JNI_TRUE); 234 } 235 236 JNIEXPORT jboolean JNICALL 237 Java_sun_font_FontManager_isCreatedFont( 238 JNIEnv *env, 239 jclass clsFM, 240 jobject javaFont) { 241 return (*env)->GetBooleanField(env, javaFont, sunFontIDs.createdFont); 242 } 243 244 /* 245 * Class: sun_font_StrikeCache 246 * Method: freeIntPointer 247 * Signature: (I)V 248 */ 249 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntPointer 250 (JNIEnv *env, jclass cacheClass, jint ptr) { 251 252 /* Note this is used for freeing a glyph which was allocated 253 * but never placed into the glyph cache. The caller holds the 254 * only reference, therefore it is unnecessary to invalidate any 255 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 256 */ 257 if (ptr != 0) { 258 free((void*)ptr); 259 } 260 } 261 262 /* 263 * Class: sun_font_StrikeCache 264 * Method: freeLongPointer 265 * Signature: (J)V 266 */ 267 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongPointer 268 (JNIEnv *env, jclass cacheClass, jlong ptr) { 269 270 /* Note this is used for freeing a glyph which was allocated 271 * but never placed into the glyph cache. The caller holds the 272 * only reference, therefore it is unnecessary to invalidate any 273 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 274 */ 275 if (ptr != 0L) { 276 free(jlong_to_ptr(ptr)); 277 } 278 } 279 280 /* 281 * Class: sun_font_StrikeCache 282 * Method: freeIntMemory 283 * Signature: ([I)V 284 */ 285 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory 286 (JNIEnv *env, jclass cacheClass, jintArray jmemArray, jlong pContext) { 287 288 int len = (*env)->GetArrayLength(env, jmemArray); 289 jint* ptrs = 290 (jint*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 291 int i; 292 293 if (ptrs) { 294 for (i=0; i< len; i++) { 295 if (ptrs[i] != 0) { 296 GlyphInfo *ginfo = (GlyphInfo *)ptrs[i]; 297 if (ginfo->cellInfo != NULL) { 298 // invalidate this glyph's accelerated cache cell 299 AccelGlyphCache_RemoveAllCellInfos(ginfo); 300 } 301 free((void*)ginfo); 302 } 303 } 304 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 305 } 306 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 307 free(jlong_to_ptr(pContext)); 308 } 309 } 310 311 /* 312 * Class: sun_font_StrikeCache 313 * Method: freeLongMemory 314 * Signature: ([J)V 315 */ 316 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory 317 (JNIEnv *env, jclass cacheClass, jlongArray jmemArray, jlong pContext) { 318 319 int len = (*env)->GetArrayLength(env, jmemArray); 320 jlong* ptrs = 321 (jlong*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 322 int i; 323 324 if (ptrs) { 325 for (i=0; i< len; i++) { 326 if (ptrs[i] != 0L) { 327 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]); 328 if (ginfo->cellInfo != NULL) { 329 AccelGlyphCache_RemoveAllCellInfos(ginfo); 330 } 331 free((void*)ginfo); 332 } 333 } 334 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 335 } 336 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 337 free(jlong_to_ptr(pContext)); 338 } 339 } 340 341 JNIEXPORT void JNICALL 342 Java_sun_font_StrikeCache_getGlyphCacheDescription 343 (JNIEnv *env, jclass cls, jlongArray results) { 344 345 jlong* nresults; 346 GlyphInfo *info; 347 size_t baseAddr; 348 349 if ((*env)->GetArrayLength(env, results) < 10) { 350 return; 351 } 352 353 nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL); 354 if (nresults == NULL) { 355 return; 356 } 357 info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo)); 358 if (info == NULL) { 359 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 360 return; 361 } 362 baseAddr = (size_t)info; 363 nresults[0] = sizeof(void*); 364 nresults[1] = sizeof(GlyphInfo); 365 nresults[2] = 0; 366 nresults[3] = (size_t)&(info->advanceY)-baseAddr; 367 nresults[4] = (size_t)&(info->width)-baseAddr; 368 nresults[5] = (size_t)&(info->height)-baseAddr; 369 nresults[6] = (size_t)&(info->rowBytes)-baseAddr; 370 nresults[7] = (size_t)&(info->topLeftX)-baseAddr; 371 nresults[8] = (size_t)&(info->topLeftY)-baseAddr; 372 nresults[9] = (size_t)&(info->image)-baseAddr; 373 nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */ 374 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 375 } 376 377 JNIEXPORT TTLayoutTableCache* newLayoutTableCache() { 378 TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache)); 379 if (ltc) { 380 ltc->gsub_len = -1; 381 ltc->gpos_len = -1; 382 ltc->gdef_len = -1; 383 ltc->mort_len = -1; 384 ltc->kern_len = -1; 385 } 386 return ltc; 387 } 388 389 JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) { 390 if (ltc) { 391 if (ltc->gsub) free(ltc->gsub); 392 if (ltc->gpos) free(ltc->gpos); 393 if (ltc->gdef) free(ltc->gdef); 394 if (ltc->mort) free(ltc->mort); 395 if (ltc->kern) free(ltc->kern); 396 if (ltc->kernPairs) free(ltc->kernPairs); 397 free(ltc); 398 } 399 }