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