1 /* 2 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "stdlib.h" 27 #include "string.h" 28 #include "gdefs.h" 29 #include "jlong.h" 30 #include "jni_util.h" 31 #include "sunfontids.h" 32 #include "fontscalerdefs.h" 33 #include "sun_font_SunFontManager.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 * Declare library specific JNI_Onload entry if static build 42 */ 43 DEF_STATIC_JNI_OnLoad 44 45 JNIEXPORT jlong JNICALL 46 Java_sun_font_NullFontScaler_getNullScalerContext 47 (JNIEnv *env, jclass scalerClass) { 48 49 if (theNullScalerContext == NULL) { 50 theNullScalerContext = malloc(1); 51 } 52 return ptr_to_jlong(theNullScalerContext); 53 } 54 55 int isNullScalerContext(void *context) { 56 return theNullScalerContext == context; 57 } 58 59 /* Eventually we may rework it to be a singleton. 60 * This will require additional checks in freeLongMemory/freeIntMemory 61 * and on other hand malformed fonts (main source of null glyph images) 62 * are supposed to be collected fast. 63 * But perhaps it is still right thing to do. 64 * Even better is to eliminate the need to have this native method 65 * but for this it is necessary to rework Strike and drawing logic 66 * to be able to live with NULL pointers without performance hit. 67 */ 68 JNIEXPORT jlong JNICALL Java_sun_font_NullFontScaler_getGlyphImage 69 (JNIEnv *env, jobject scaler, jlong pContext, jint glyphCode) { 70 void *nullscaler = calloc(sizeof(GlyphInfo), 1); 71 return ptr_to_jlong(nullscaler); 72 } 73 74 75 76 void initLCDGammaTables(); 77 78 /* placeholder for extern variable */ 79 static int initialisedFontIDs = 0; 80 FontManagerNativeIDs sunFontIDs; 81 82 static void initFontIDs(JNIEnv *env) { 83 84 jclass tmpClass; 85 86 if (initialisedFontIDs) { 87 return; 88 } 89 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont")); 90 CHECK_NULL(sunFontIDs.ttReadBlockMID = 91 (*env)->GetMethodID(env, tmpClass, "readBlock", 92 "(Ljava/nio/ByteBuffer;II)I")); 93 CHECK_NULL(sunFontIDs.ttReadBytesMID = 94 (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B")); 95 96 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Type1Font")); 97 CHECK_NULL(sunFontIDs.readFileMID = 98 (*env)->GetMethodID(env, tmpClass, 99 "readFile", "(Ljava/nio/ByteBuffer;)V")); 100 101 CHECK_NULL(tmpClass = 102 (*env)->FindClass(env, "java/awt/geom/Point2D$Float")); 103 sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 104 CHECK_NULL(sunFontIDs.pt2DFloatCtr = 105 (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V")); 106 107 CHECK_NULL(sunFontIDs.xFID = 108 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F")); 109 CHECK_NULL(sunFontIDs.yFID = 110 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F")); 111 112 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics")); 113 CHECK_NULL(sunFontIDs.strikeMetricsClass = 114 (jclass)(*env)->NewGlobalRef(env, tmpClass)); 115 116 CHECK_NULL(sunFontIDs.strikeMetricsCtr = 117 (*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass, 118 "<init>", "(FFFFFFFFFF)V")); 119 120 CHECK_NULL(tmpClass = 121 (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float")); 122 sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 123 CHECK_NULL(sunFontIDs.rect2DFloatCtr = 124 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V")); 125 CHECK_NULL(sunFontIDs.rect2DFloatCtr4 = 126 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, 127 "<init>", "(FFFF)V")); 128 CHECK_NULL(sunFontIDs.rectF2DX = 129 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F")); 130 CHECK_NULL(sunFontIDs.rectF2DY = 131 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F")); 132 CHECK_NULL(sunFontIDs.rectF2DWidth = 133 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F")); 134 CHECK_NULL(sunFontIDs.rectF2DHeight = 135 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F")); 136 137 CHECK_NULL(tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath")); 138 sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 139 CHECK_NULL(sunFontIDs.gpCtr = 140 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V")); 141 CHECK_NULL(sunFontIDs.gpCtrEmpty = 142 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V")); 143 144 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Font2D")); 145 CHECK_NULL(sunFontIDs.f2dCharToGlyphMID = 146 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I")); 147 CHECK_NULL(sunFontIDs.f2dCharsToGlyphsMID = 148 (*env)->GetMethodID(env, tmpClass, "charsToGlyphs", "(I[I[I)V")); 149 CHECK_NULL(sunFontIDs.getMapperMID = 150 (*env)->GetMethodID(env, tmpClass, "getMapper", 151 "()Lsun/font/CharToGlyphMapper;")); 152 CHECK_NULL(sunFontIDs.getTableBytesMID = 153 (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B")); 154 CHECK_NULL(sunFontIDs.canDisplayMID = 155 (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z")); 156 157 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper")); 158 CHECK_NULL(sunFontIDs.charToGlyphMID = 159 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I")); 160 CHECK_NULL(sunFontIDs.charsToGlyphsMID = 161 (*env)->GetMethodID(env, tmpClass, "charsToGlyphs", "(I[I[I)V")); 162 163 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike")); 164 CHECK_NULL(sunFontIDs.getGlyphMetricsMID = 165 (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics", 166 "(I)Ljava/awt/geom/Point2D$Float;")); 167 CHECK_NULL(sunFontIDs.getGlyphPointMID = 168 (*env)->GetMethodID(env, tmpClass, "getGlyphPoint", 169 "(II)Ljava/awt/geom/Point2D$Float;")); 170 CHECK_NULL(sunFontIDs.adjustPointMID = 171 (*env)->GetMethodID(env, tmpClass, "adjustPoint", 172 "(Ljava/awt/geom/Point2D$Float;)V")); 173 CHECK_NULL(sunFontIDs.pScalerContextFID = 174 (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J")); 175 176 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/GlyphList")); 177 CHECK_NULL(sunFontIDs.glyphListX = 178 (*env)->GetFieldID(env, tmpClass, "x", "F")); 179 CHECK_NULL(sunFontIDs.glyphListY = 180 (*env)->GetFieldID(env, tmpClass, "y", "F")); 181 CHECK_NULL(sunFontIDs.glyphListLen = 182 (*env)->GetFieldID(env, tmpClass, "len", "I")); 183 CHECK_NULL(sunFontIDs.glyphImages = 184 (*env)->GetFieldID(env, tmpClass, "images", "[J")); 185 CHECK_NULL(sunFontIDs.glyphListUsePos = 186 (*env)->GetFieldID(env, tmpClass, "usePositions", "Z")); 187 CHECK_NULL(sunFontIDs.glyphListPos = 188 (*env)->GetFieldID(env, tmpClass, "positions", "[F")); 189 CHECK_NULL(sunFontIDs.lcdRGBOrder = 190 (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z")); 191 CHECK_NULL(sunFontIDs.lcdSubPixPos = 192 (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z")); 193 194 initLCDGammaTables(); 195 196 initialisedFontIDs = 1; 197 } 198 199 JNIEXPORT void JNICALL 200 Java_sun_font_SunFontManager_initIDs 201 (JNIEnv *env, jclass cls) { 202 203 initFontIDs(env); 204 } 205 206 JNIEXPORT FontManagerNativeIDs getSunFontIDs(JNIEnv *env) { 207 208 initFontIDs(env); 209 return sunFontIDs; 210 } 211 212 /* 213 * Class: sun_font_StrikeCache 214 * Method: freeIntPointer 215 * Signature: (I)V 216 */ 217 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntPointer 218 (JNIEnv *env, jclass cacheClass, jint ptr) { 219 220 /* Note this is used for freeing a glyph which was allocated 221 * but never placed into the glyph cache. The caller holds the 222 * only reference, therefore it is unnecessary to invalidate any 223 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 224 */ 225 if (ptr != 0) { 226 free((void*)((intptr_t)ptr)); 227 } 228 } 229 230 /* 231 * Class: sun_font_StrikeCache 232 * Method: freeLongPointer 233 * Signature: (J)V 234 */ 235 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongPointer 236 (JNIEnv *env, jclass cacheClass, jlong ptr) { 237 238 /* Note this is used for freeing a glyph which was allocated 239 * but never placed into the glyph cache. The caller holds the 240 * only reference, therefore it is unnecessary to invalidate any 241 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 242 */ 243 if (ptr != 0L) { 244 free(jlong_to_ptr(ptr)); 245 } 246 } 247 248 /* 249 * Class: sun_font_StrikeCache 250 * Method: freeIntMemory 251 * Signature: ([I)V 252 */ 253 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory 254 (JNIEnv *env, jclass cacheClass, jintArray jmemArray, jlong pContext) { 255 256 int len = (*env)->GetArrayLength(env, jmemArray); 257 jint* ptrs = 258 (jint*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 259 int i; 260 261 if (ptrs) { 262 for (i=0; i< len; i++) { 263 if (ptrs[i] != 0) { 264 GlyphInfo *ginfo = (GlyphInfo *)((intptr_t)ptrs[i]); 265 if (ginfo->cellInfo != NULL && 266 ginfo->managed == MANAGED_GLYPH) { 267 // invalidate this glyph's accelerated cache cell 268 AccelGlyphCache_RemoveAllCellInfos(ginfo); 269 } 270 free(ginfo); 271 } 272 } 273 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 274 } 275 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 276 free(jlong_to_ptr(pContext)); 277 } 278 } 279 280 /* 281 * Class: sun_font_StrikeCache 282 * Method: freeLongMemory 283 * Signature: ([J)V 284 */ 285 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory 286 (JNIEnv *env, jclass cacheClass, jlongArray jmemArray, jlong pContext) { 287 288 int len = (*env)->GetArrayLength(env, jmemArray); 289 jlong* ptrs = 290 (jlong*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 291 int i; 292 293 if (ptrs) { 294 for (i=0; i< len; i++) { 295 if (ptrs[i] != 0L) { 296 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]); 297 if (ginfo->cellInfo != NULL && 298 ginfo->managed == MANAGED_GLYPH) { 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 JNIEXPORT void JNICALL 312 Java_sun_font_StrikeCache_getGlyphCacheDescription 313 (JNIEnv *env, jclass cls, jlongArray results) { 314 315 jlong* nresults; 316 GlyphInfo *info; 317 size_t baseAddr; 318 319 if ((*env)->GetArrayLength(env, results) < 13) { 320 return; 321 } 322 323 nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL); 324 if (nresults == NULL) { 325 return; 326 } 327 info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo)); 328 if (info == NULL) { 329 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 330 return; 331 } 332 baseAddr = (size_t)info; 333 nresults[0] = sizeof(void*); 334 nresults[1] = sizeof(GlyphInfo); 335 nresults[2] = 0; 336 nresults[3] = (size_t)&(info->advanceY)-baseAddr; 337 nresults[4] = (size_t)&(info->width)-baseAddr; 338 nresults[5] = (size_t)&(info->height)-baseAddr; 339 nresults[6] = (size_t)&(info->rowBytes)-baseAddr; 340 nresults[7] = (size_t)&(info->topLeftX)-baseAddr; 341 nresults[8] = (size_t)&(info->topLeftY)-baseAddr; 342 nresults[9] = (size_t)&(info->image)-baseAddr; 343 nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */ 344 nresults[11] = (size_t)&(info->cellInfo)-baseAddr; 345 nresults[12] = (size_t)&(info->managed)-baseAddr; 346 347 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 348 } 349 350 JNIEXPORT TTLayoutTableCache* newLayoutTableCache() { 351 TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache)); 352 if (ltc) { 353 int i; 354 for(i=0;i<LAYOUTCACHE_ENTRIES;i++) { 355 ltc->entries[i].len = -1; 356 } 357 ltc->entries[0].tag = GDEF_TAG; 358 ltc->entries[1].tag = GPOS_TAG; 359 ltc->entries[2].tag = GSUB_TAG; 360 ltc->entries[3].tag = HEAD_TAG; 361 ltc->entries[4].tag = KERN_TAG; 362 ltc->entries[5].tag = MORT_TAG; 363 ltc->entries[6].tag = MORX_TAG; 364 } 365 return ltc; 366 } 367 368 JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) { 369 if (ltc) { 370 int i; 371 for(i=0;i<LAYOUTCACHE_ENTRIES;i++) { 372 if(ltc->entries[i].ptr) free (ltc->entries[i].ptr); 373 } 374 if (ltc->kernPairs) free(ltc->kernPairs); 375 free(ltc); 376 } 377 }