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