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.f2dCharToVariationGlyphMID = 148 (*env)->GetMethodID(env, tmpClass, "charToVariationGlyph", "(II)I")); 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 161 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike")); 162 CHECK_NULL(sunFontIDs.getGlyphMetricsMID = 163 (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics", 164 "(I)Ljava/awt/geom/Point2D$Float;")); 165 CHECK_NULL(sunFontIDs.getGlyphPointMID = 166 (*env)->GetMethodID(env, tmpClass, "getGlyphPoint", 167 "(II)Ljava/awt/geom/Point2D$Float;")); 168 CHECK_NULL(sunFontIDs.adjustPointMID = 169 (*env)->GetMethodID(env, tmpClass, "adjustPoint", 170 "(Ljava/awt/geom/Point2D$Float;)V")); 171 CHECK_NULL(sunFontIDs.pScalerContextFID = 172 (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J")); 173 174 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/GlyphList")); 175 CHECK_NULL(sunFontIDs.glyphListX = 176 (*env)->GetFieldID(env, tmpClass, "x", "F")); 177 CHECK_NULL(sunFontIDs.glyphListY = 178 (*env)->GetFieldID(env, tmpClass, "y", "F")); 179 CHECK_NULL(sunFontIDs.glyphListLen = 180 (*env)->GetFieldID(env, tmpClass, "len", "I")); 181 CHECK_NULL(sunFontIDs.glyphImages = 182 (*env)->GetFieldID(env, tmpClass, "images", "[J")); 183 CHECK_NULL(sunFontIDs.glyphListUsePos = 184 (*env)->GetFieldID(env, tmpClass, "usePositions", "Z")); 185 CHECK_NULL(sunFontIDs.glyphListPos = 186 (*env)->GetFieldID(env, tmpClass, "positions", "[F")); 187 CHECK_NULL(sunFontIDs.lcdRGBOrder = 188 (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z")); 189 CHECK_NULL(sunFontIDs.lcdSubPixPos = 190 (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z")); 191 192 initLCDGammaTables(); 193 194 initialisedFontIDs = 1; 195 } 196 197 JNIEXPORT void JNICALL 198 Java_sun_font_SunFontManager_initIDs 199 (JNIEnv *env, jclass cls) { 200 201 initFontIDs(env); 202 } 203 204 JNIEXPORT FontManagerNativeIDs getSunFontIDs(JNIEnv *env) { 205 206 initFontIDs(env); 207 return sunFontIDs; 208 } 209 210 /* 211 * Class: sun_font_StrikeCache 212 * Method: freeIntPointer 213 * Signature: (I)V 214 */ 215 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntPointer 216 (JNIEnv *env, jclass cacheClass, jint ptr) { 217 218 /* Note this is used for freeing a glyph which was allocated 219 * but never placed into the glyph cache. The caller holds the 220 * only reference, therefore it is unnecessary to invalidate any 221 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 222 */ 223 if (ptr != 0) { 224 free((void*)((intptr_t)ptr)); 225 } 226 } 227 228 /* 229 * Class: sun_font_StrikeCache 230 * Method: freeLongPointer 231 * Signature: (J)V 232 */ 233 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongPointer 234 (JNIEnv *env, jclass cacheClass, jlong ptr) { 235 236 /* Note this is used for freeing a glyph which was allocated 237 * but never placed into the glyph cache. The caller holds the 238 * only reference, therefore it is unnecessary to invalidate any 239 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 240 */ 241 if (ptr != 0L) { 242 free(jlong_to_ptr(ptr)); 243 } 244 } 245 246 /* 247 * Class: sun_font_StrikeCache 248 * Method: freeIntMemory 249 * Signature: ([I)V 250 */ 251 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory 252 (JNIEnv *env, jclass cacheClass, jintArray jmemArray, jlong pContext) { 253 254 int len = (*env)->GetArrayLength(env, jmemArray); 255 jint* ptrs = 256 (jint*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 257 int i; 258 259 if (ptrs) { 260 for (i=0; i< len; i++) { 261 if (ptrs[i] != 0) { 262 GlyphInfo *ginfo = (GlyphInfo *)((intptr_t)ptrs[i]); 263 if (ginfo->cellInfo != NULL && 264 ginfo->managed == MANAGED_GLYPH) { 265 // invalidate this glyph's accelerated cache cell 266 AccelGlyphCache_RemoveAllCellInfos(ginfo); 267 } 268 free(ginfo); 269 } 270 } 271 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 272 } 273 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 274 free(jlong_to_ptr(pContext)); 275 } 276 } 277 278 /* 279 * Class: sun_font_StrikeCache 280 * Method: freeLongMemory 281 * Signature: ([J)V 282 */ 283 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory 284 (JNIEnv *env, jclass cacheClass, jlongArray jmemArray, jlong pContext) { 285 286 int len = (*env)->GetArrayLength(env, jmemArray); 287 jlong* ptrs = 288 (jlong*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 289 int i; 290 291 if (ptrs) { 292 for (i=0; i< len; i++) { 293 if (ptrs[i] != 0L) { 294 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]); 295 if (ginfo->cellInfo != NULL && 296 ginfo->managed == MANAGED_GLYPH) { 297 AccelGlyphCache_RemoveAllCellInfos(ginfo); 298 } 299 free((void*)ginfo); 300 } 301 } 302 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 303 } 304 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 305 free(jlong_to_ptr(pContext)); 306 } 307 } 308 309 JNIEXPORT void JNICALL 310 Java_sun_font_StrikeCache_getGlyphCacheDescription 311 (JNIEnv *env, jclass cls, jlongArray results) { 312 313 jlong* nresults; 314 GlyphInfo *info; 315 size_t baseAddr; 316 317 if ((*env)->GetArrayLength(env, results) < 13) { 318 return; 319 } 320 321 nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL); 322 if (nresults == NULL) { 323 return; 324 } 325 info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo)); 326 if (info == NULL) { 327 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 328 return; 329 } 330 baseAddr = (size_t)info; 331 nresults[0] = sizeof(void*); 332 nresults[1] = sizeof(GlyphInfo); 333 nresults[2] = 0; 334 nresults[3] = (size_t)&(info->advanceY)-baseAddr; 335 nresults[4] = (size_t)&(info->width)-baseAddr; 336 nresults[5] = (size_t)&(info->height)-baseAddr; 337 nresults[6] = (size_t)&(info->rowBytes)-baseAddr; 338 nresults[7] = (size_t)&(info->topLeftX)-baseAddr; 339 nresults[8] = (size_t)&(info->topLeftY)-baseAddr; 340 nresults[9] = (size_t)&(info->image)-baseAddr; 341 nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */ 342 nresults[11] = (size_t)&(info->cellInfo)-baseAddr; 343 nresults[12] = (size_t)&(info->managed)-baseAddr; 344 345 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 346 } 347 348 JNIEXPORT TTLayoutTableCache* newLayoutTableCache() { 349 TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache)); 350 if (ltc) { 351 int i; 352 for(i=0;i<LAYOUTCACHE_ENTRIES;i++) { 353 ltc->entries[i].len = -1; 354 } 355 ltc->entries[0].tag = GDEF_TAG; 356 ltc->entries[1].tag = GPOS_TAG; 357 ltc->entries[2].tag = GSUB_TAG; 358 ltc->entries[3].tag = HEAD_TAG; 359 ltc->entries[4].tag = KERN_TAG; 360 ltc->entries[5].tag = MORT_TAG; 361 ltc->entries[6].tag = MORX_TAG; 362 } 363 return ltc; 364 } 365 366 JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) { 367 if (ltc) { 368 int i; 369 for(i=0;i<LAYOUTCACHE_ENTRIES;i++) { 370 if(ltc->entries[i].ptr) free (ltc->entries[i].ptr); 371 } 372 if (ltc->kernPairs) free(ltc->kernPairs); 373 free(ltc); 374 } 375 }