1 /* 2 * Copyright (c) 2007, 2013, 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 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 /* placeholder for extern variable */ 75 static int initialisedFontIDs = 0; 76 FontManagerNativeIDs sunFontIDs; 77 78 static void initFontIDs(JNIEnv *env) { 79 80 jclass tmpClass; 81 82 if (initialisedFontIDs) { 83 return; 84 } 85 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont")); 86 CHECK_NULL(sunFontIDs.ttReadBlockMID = 87 (*env)->GetMethodID(env, tmpClass, "readBlock", 88 "(Ljava/nio/ByteBuffer;II)I")); 89 CHECK_NULL(sunFontIDs.ttReadBytesMID = 90 (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B")); 91 92 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Type1Font")); 93 CHECK_NULL(sunFontIDs.readFileMID = 94 (*env)->GetMethodID(env, tmpClass, 95 "readFile", "(Ljava/nio/ByteBuffer;)V")); 96 97 CHECK_NULL(tmpClass = 98 (*env)->FindClass(env, "java/awt/geom/Point2D$Float")); 99 sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 100 CHECK_NULL(sunFontIDs.pt2DFloatCtr = 101 (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V")); 102 103 CHECK_NULL(sunFontIDs.xFID = 104 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F")); 105 CHECK_NULL(sunFontIDs.yFID = 106 (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F")); 107 108 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics")); 109 CHECK_NULL(sunFontIDs.strikeMetricsClass = 110 (jclass)(*env)->NewGlobalRef(env, tmpClass)); 111 112 CHECK_NULL(sunFontIDs.strikeMetricsCtr = 113 (*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass, 114 "<init>", "(FFFFFFFFFF)V")); 115 116 CHECK_NULL(tmpClass = 117 (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float")); 118 sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 119 CHECK_NULL(sunFontIDs.rect2DFloatCtr = 120 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V")); 121 CHECK_NULL(sunFontIDs.rect2DFloatCtr4 = 122 (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, 123 "<init>", "(FFFF)V")); 124 CHECK_NULL(sunFontIDs.rectF2DX = 125 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F")); 126 CHECK_NULL(sunFontIDs.rectF2DY = 127 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F")); 128 CHECK_NULL(sunFontIDs.rectF2DWidth = 129 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F")); 130 CHECK_NULL(sunFontIDs.rectF2DHeight = 131 (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F")); 132 133 CHECK_NULL(tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath")); 134 sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 135 CHECK_NULL(sunFontIDs.gpCtr = 136 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V")); 137 CHECK_NULL(sunFontIDs.gpCtrEmpty = 138 (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V")); 139 140 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Font2D")); 141 CHECK_NULL(sunFontIDs.f2dCharToGlyphMID = 142 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I")); 143 CHECK_NULL(sunFontIDs.getMapperMID = 144 (*env)->GetMethodID(env, tmpClass, "getMapper", 145 "()Lsun/font/CharToGlyphMapper;")); 146 CHECK_NULL(sunFontIDs.getTableBytesMID = 147 (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B")); 148 CHECK_NULL(sunFontIDs.canDisplayMID = 149 (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z")); 150 151 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper")); 152 CHECK_NULL(sunFontIDs.charToGlyphMID = 153 (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I")); 154 155 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike")); 156 CHECK_NULL(sunFontIDs.getGlyphMetricsMID = 157 (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics", 158 "(I)Ljava/awt/geom/Point2D$Float;")); 159 CHECK_NULL(sunFontIDs.getGlyphPointMID = 160 (*env)->GetMethodID(env, tmpClass, "getGlyphPoint", 161 "(II)Ljava/awt/geom/Point2D$Float;")); 162 CHECK_NULL(sunFontIDs.adjustPointMID = 163 (*env)->GetMethodID(env, tmpClass, "adjustPoint", 164 "(Ljava/awt/geom/Point2D$Float;)V")); 165 CHECK_NULL(sunFontIDs.pScalerContextFID = 166 (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J")); 167 168 CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/GlyphList")); 169 CHECK_NULL(sunFontIDs.glyphListX = 170 (*env)->GetFieldID(env, tmpClass, "x", "F")); 171 CHECK_NULL(sunFontIDs.glyphListY = 172 (*env)->GetFieldID(env, tmpClass, "y", "F")); 173 CHECK_NULL(sunFontIDs.glyphListLen = 174 (*env)->GetFieldID(env, tmpClass, "len", "I")); 175 CHECK_NULL(sunFontIDs.glyphImages = 176 (*env)->GetFieldID(env, tmpClass, "images", "[J")); 177 CHECK_NULL(sunFontIDs.glyphListUsePos = 178 (*env)->GetFieldID(env, tmpClass, "usePositions", "Z")); 179 CHECK_NULL(sunFontIDs.glyphListPos = 180 (*env)->GetFieldID(env, tmpClass, "positions", "[F")); 181 CHECK_NULL(sunFontIDs.lcdRGBOrder = 182 (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z")); 183 CHECK_NULL(sunFontIDs.lcdSubPixPos = 184 (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z")); 185 186 initLCDGammaTables(); 187 188 initialisedFontIDs = 1; 189 } 190 191 JNIEXPORT void JNICALL 192 Java_sun_font_SunFontManager_initIDs 193 (JNIEnv *env, jclass cls) { 194 195 initFontIDs(env); 196 } 197 198 JNIEXPORT FontManagerNativeIDs getSunFontIDs(JNIEnv *env) { 199 200 initFontIDs(env); 201 return sunFontIDs; 202 } 203 204 /* 205 * Class: sun_font_StrikeCache 206 * Method: freeIntPointer 207 * Signature: (I)V 208 */ 209 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntPointer 210 (JNIEnv *env, jclass cacheClass, jint ptr) { 211 212 /* Note this is used for freeing a glyph which was allocated 213 * but never placed into the glyph cache. The caller holds the 214 * only reference, therefore it is unnecessary to invalidate any 215 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 216 */ 217 if (ptr != 0) { 218 free((void*)ptr); 219 } 220 } 221 222 /* 223 * Class: sun_font_StrikeCache 224 * Method: freeLongPointer 225 * Signature: (J)V 226 */ 227 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongPointer 228 (JNIEnv *env, jclass cacheClass, jlong ptr) { 229 230 /* Note this is used for freeing a glyph which was allocated 231 * but never placed into the glyph cache. The caller holds the 232 * only reference, therefore it is unnecessary to invalidate any 233 * accelerated glyph cache cells as we do in freeInt/LongMemory(). 234 */ 235 if (ptr != 0L) { 236 free(jlong_to_ptr(ptr)); 237 } 238 } 239 240 /* 241 * Class: sun_font_StrikeCache 242 * Method: freeIntMemory 243 * Signature: ([I)V 244 */ 245 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory 246 (JNIEnv *env, jclass cacheClass, jintArray jmemArray, jlong pContext) { 247 248 int len = (*env)->GetArrayLength(env, jmemArray); 249 jint* ptrs = 250 (jint*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 251 int i; 252 253 if (ptrs) { 254 for (i=0; i< len; i++) { 255 if (ptrs[i] != 0) { 256 GlyphInfo *ginfo = (GlyphInfo *)ptrs[i]; 257 if (ginfo->cellInfo != NULL && 258 ginfo->managed == MANAGED_GLYPH) { 259 // invalidate this glyph's accelerated cache cell 260 AccelGlyphCache_RemoveAllCellInfos(ginfo); 261 } 262 free((void*)ginfo); 263 } 264 } 265 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 266 } 267 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 268 free(jlong_to_ptr(pContext)); 269 } 270 } 271 272 /* 273 * Class: sun_font_StrikeCache 274 * Method: freeLongMemory 275 * Signature: ([J)V 276 */ 277 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory 278 (JNIEnv *env, jclass cacheClass, jlongArray jmemArray, jlong pContext) { 279 280 int len = (*env)->GetArrayLength(env, jmemArray); 281 jlong* ptrs = 282 (jlong*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL); 283 int i; 284 285 if (ptrs) { 286 for (i=0; i< len; i++) { 287 if (ptrs[i] != 0L) { 288 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]); 289 if (ginfo->cellInfo != NULL && 290 ginfo->managed == MANAGED_GLYPH) { 291 AccelGlyphCache_RemoveAllCellInfos(ginfo); 292 } 293 free((void*)ginfo); 294 } 295 } 296 (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT); 297 } 298 if (!isNullScalerContext(jlong_to_ptr(pContext))) { 299 free(jlong_to_ptr(pContext)); 300 } 301 } 302 303 JNIEXPORT void JNICALL 304 Java_sun_font_StrikeCache_getGlyphCacheDescription 305 (JNIEnv *env, jclass cls, jlongArray results) { 306 307 jlong* nresults; 308 GlyphInfo *info; 309 size_t baseAddr; 310 311 if ((*env)->GetArrayLength(env, results) < 13) { 312 return; 313 } 314 315 nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL); 316 if (nresults == NULL) { 317 return; 318 } 319 info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo)); 320 if (info == NULL) { 321 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 322 return; 323 } 324 baseAddr = (size_t)info; 325 nresults[0] = sizeof(void*); 326 nresults[1] = sizeof(GlyphInfo); 327 nresults[2] = 0; 328 nresults[3] = (size_t)&(info->advanceY)-baseAddr; 329 nresults[4] = (size_t)&(info->width)-baseAddr; 330 nresults[5] = (size_t)&(info->height)-baseAddr; 331 nresults[6] = (size_t)&(info->rowBytes)-baseAddr; 332 nresults[7] = (size_t)&(info->topLeftX)-baseAddr; 333 nresults[8] = (size_t)&(info->topLeftY)-baseAddr; 334 nresults[9] = (size_t)&(info->image)-baseAddr; 335 nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */ 336 nresults[11] = (size_t)&(info->cellInfo)-baseAddr; 337 nresults[12] = (size_t)&(info->managed)-baseAddr; 338 339 (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); 340 } 341 342 JNIEXPORT TTLayoutTableCache* newLayoutTableCache() { 343 TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache)); 344 if (ltc) { 345 int i; 346 for(i=0;i<LAYOUTCACHE_ENTRIES;i++) { 347 ltc->entries[i].len = -1; 348 } 349 } 350 return ltc; 351 } 352 353 JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) { 354 if (ltc) { 355 int i; 356 for(i=0;i<LAYOUTCACHE_ENTRIES;i++) { 357 if(ltc->entries[i].ptr) free (ltc->entries[i].ptr); 358 } 359 if (ltc->kernPairs) free(ltc->kernPairs); 360 free(ltc); 361 } 362 }