1 /*
   2  * Copyright 2007-2008 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any 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 /*
  75  * Class:     sun_font_FontManager
  76  * Method:    getPlatformFontVar
  77  * Signature: ()Z
  78  */
  79 JNIEXPORT jboolean JNICALL
  80 Java_sun_font_FontManager_getPlatformFontVar(JNIEnv *env, jclass cl) {
  81     char *c = getenv("JAVA2D_USEPLATFORMFONT");
  82     if (c) {
  83         return JNI_TRUE;
  84     } else {
  85         return JNI_FALSE;
  86     }
  87 }
  88 
  89 /* placeholder for extern variable */
  90 FontManagerNativeIDs sunFontIDs;
  91 
  92 JNIEXPORT void JNICALL
  93 Java_sun_font_FontManager_initIDs
  94     (JNIEnv *env, jclass cls) {
  95 
  96      jclass tmpClass = (*env)->FindClass(env, "java/awt/Font");
  97 
  98      sunFontIDs.getFont2DMID =
  99          (*env)->GetMethodID(env, tmpClass, "getFont2D",
 100                              "()Lsun/font/Font2D;");
 101      sunFontIDs.font2DHandle =
 102        (*env)->GetFieldID(env, tmpClass,
 103                           "font2DHandle", "Lsun/font/Font2DHandle;");
 104 
 105      sunFontIDs.createdFont =
 106        (*env)->GetFieldID(env, tmpClass, "createdFont", "Z");
 107 
 108      tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont");
 109      sunFontIDs.ttReadBlockMID =
 110          (*env)->GetMethodID(env, tmpClass, "readBlock",
 111                              "(Ljava/nio/ByteBuffer;II)I");
 112      sunFontIDs.ttReadBytesMID =
 113          (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B");
 114 
 115      tmpClass = (*env)->FindClass(env, "sun/font/Type1Font");
 116      sunFontIDs.readFileMID =
 117          (*env)->GetMethodID(env, tmpClass,
 118                              "readFile", "(Ljava/nio/ByteBuffer;)V");
 119 
 120      tmpClass = (*env)->FindClass(env, "java/awt/geom/Point2D$Float");
 121      sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
 122      sunFontIDs.pt2DFloatCtr =
 123          (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V");
 124 
 125      sunFontIDs.xFID =
 126          (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F");
 127      sunFontIDs.yFID =
 128          (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F");
 129 
 130      tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics");
 131      sunFontIDs.strikeMetricsClass=(jclass)(*env)->NewGlobalRef(env, tmpClass);
 132 
 133      sunFontIDs.strikeMetricsCtr =
 134          (*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass,
 135                              "<init>", "(FFFFFFFFFF)V");
 136 
 137      tmpClass = (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float");
 138      sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
 139      sunFontIDs.rect2DFloatCtr =
 140        (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V");
 141      sunFontIDs.rect2DFloatCtr4 =
 142        (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass,
 143                            "<init>", "(FFFF)V");
 144      sunFontIDs.rectF2DX =
 145          (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F");
 146      sunFontIDs.rectF2DY =
 147          (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F");
 148      sunFontIDs.rectF2DWidth =
 149          (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F");
 150      sunFontIDs.rectF2DHeight =
 151          (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F");
 152 
 153      tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath");
 154      sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
 155      sunFontIDs.gpCtr =
 156        (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V");
 157      sunFontIDs.gpCtrEmpty =
 158        (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V");
 159 
 160      tmpClass = (*env)->FindClass(env, "sun/font/Font2D");
 161      sunFontIDs.f2dCharToGlyphMID =
 162          (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I");
 163      sunFontIDs.getMapperMID =
 164          (*env)->GetMethodID(env, tmpClass, "getMapper",
 165                              "()Lsun/font/CharToGlyphMapper;");
 166      sunFontIDs.getTableBytesMID =
 167          (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B");
 168      sunFontIDs.canDisplayMID =
 169          (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z");
 170 
 171      tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper");
 172      sunFontIDs.charToGlyphMID =
 173         (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I");
 174 
 175      tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike");
 176      sunFontIDs.getGlyphMetricsMID =
 177          (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics",
 178                              "(I)Ljava/awt/geom/Point2D$Float;");
 179      sunFontIDs.getGlyphPointMID =
 180          (*env)->GetMethodID(env, tmpClass, "getGlyphPoint",
 181                              "(II)Ljava/awt/geom/Point2D$Float;");
 182      sunFontIDs.adjustPointMID =
 183          (*env)->GetMethodID(env, tmpClass, "adjustPoint",
 184                              "(Ljava/awt/geom/Point2D$Float;)V");
 185      sunFontIDs.pScalerContextFID =
 186          (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J");
 187 
 188      tmpClass = (*env)->FindClass(env, "sun/font/GlyphList");
 189      sunFontIDs.glyphListX = (*env)->GetFieldID(env, tmpClass, "x", "F");
 190      sunFontIDs.glyphListY = (*env)->GetFieldID(env, tmpClass, "y", "F");
 191      sunFontIDs.glyphListLen = (*env)->GetFieldID(env, tmpClass, "len", "I");
 192      sunFontIDs.glyphImages =
 193          (*env)->GetFieldID(env, tmpClass, "images", "[J");
 194      sunFontIDs.glyphListUsePos =
 195          (*env)->GetFieldID(env, tmpClass, "usePositions", "Z");
 196      sunFontIDs.glyphListPos =
 197          (*env)->GetFieldID(env, tmpClass, "positions", "[F");
 198      sunFontIDs.lcdRGBOrder =
 199          (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z");
 200      sunFontIDs.lcdSubPixPos =
 201          (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z");
 202 
 203      initLCDGammaTables();
 204 }
 205 
 206 JNIEXPORT FontManagerNativeIDs getSunFontIDs() {
 207     return sunFontIDs;
 208 }
 209 
 210 JNIEXPORT jobject JNICALL
 211 Java_sun_font_FontManager_getFont2D(
 212   JNIEnv *env,
 213   jclass clsFM,
 214   jobject javaFont) {
 215 
 216     return (*env)->CallObjectMethod(env, javaFont, sunFontIDs.getFont2DMID);
 217 }
 218 
 219 JNIEXPORT void JNICALL
 220 Java_sun_font_FontManager_setFont2D(
 221   JNIEnv *env,
 222   jclass clsFM,
 223   jobject javaFont,
 224   jobject fontHandle) {
 225     (*env)->SetObjectField(env, javaFont, sunFontIDs.font2DHandle, fontHandle);
 226 }
 227 
 228 JNIEXPORT void JNICALL
 229 Java_sun_font_FontManager_setCreatedFont(
 230   JNIEnv *env,
 231   jclass clsFM,
 232   jobject javaFont) {
 233     (*env)->SetBooleanField(env, javaFont, sunFontIDs.createdFont, JNI_TRUE);
 234 }
 235 
 236 JNIEXPORT jboolean JNICALL
 237 Java_sun_font_FontManager_isCreatedFont(
 238   JNIEnv *env,
 239   jclass clsFM,
 240   jobject javaFont) {
 241     return (*env)->GetBooleanField(env, javaFont, sunFontIDs.createdFont);
 242 }
 243 
 244 /*
 245  * Class:     sun_font_StrikeCache
 246  * Method:    freeIntPointer
 247  * Signature: (I)V
 248  */
 249 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntPointer
 250     (JNIEnv *env, jclass cacheClass, jint ptr) {
 251 
 252     /* Note this is used for freeing a glyph which was allocated
 253      * but never placed into the glyph cache. The caller holds the
 254      * only reference, therefore it is unnecessary to invalidate any
 255      * accelerated glyph cache cells as we do in freeInt/LongMemory().
 256      */
 257     if (ptr != 0) {
 258         free((void*)ptr);
 259     }
 260 }
 261 
 262 /*
 263  * Class:     sun_font_StrikeCache
 264  * Method:    freeLongPointer
 265  * Signature: (J)V
 266  */
 267 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongPointer
 268     (JNIEnv *env, jclass cacheClass, jlong ptr) {
 269 
 270     /* Note this is used for freeing a glyph which was allocated
 271      * but never placed into the glyph cache. The caller holds the
 272      * only reference, therefore it is unnecessary to invalidate any
 273      * accelerated glyph cache cells as we do in freeInt/LongMemory().
 274      */
 275     if (ptr != 0L) {
 276         free(jlong_to_ptr(ptr));
 277     }
 278 }
 279 
 280 /*
 281  * Class:     sun_font_StrikeCache
 282  * Method:    freeIntMemory
 283  * Signature: ([I)V
 284  */
 285 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory
 286     (JNIEnv *env, jclass cacheClass, jintArray jmemArray, jlong pContext) {
 287 
 288     int len = (*env)->GetArrayLength(env, jmemArray);
 289     jint* ptrs =
 290         (jint*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL);
 291     int i;
 292 
 293     if (ptrs) {
 294         for (i=0; i< len; i++) {
 295             if (ptrs[i] != 0) {
 296                 GlyphInfo *ginfo = (GlyphInfo *)ptrs[i];
 297                 if (ginfo->cellInfo != NULL) {
 298                     // invalidate this glyph's accelerated cache cell
 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 /*
 312  * Class:     sun_font_StrikeCache
 313  * Method:    freeLongMemory
 314  * Signature: ([J)V
 315  */
 316 JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory
 317     (JNIEnv *env, jclass cacheClass, jlongArray jmemArray, jlong pContext) {
 318 
 319     int len = (*env)->GetArrayLength(env, jmemArray);
 320     jlong* ptrs =
 321         (jlong*)(*env)->GetPrimitiveArrayCritical(env, jmemArray, NULL);
 322     int i;
 323 
 324     if (ptrs) {
 325         for (i=0; i< len; i++) {
 326             if (ptrs[i] != 0L) {
 327                 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]);
 328                 if (ginfo->cellInfo != NULL) {
 329                     AccelGlyphCache_RemoveAllCellInfos(ginfo);
 330                 }
 331                 free((void*)ginfo);
 332             }
 333         }
 334         (*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT);
 335     }
 336     if (!isNullScalerContext(jlong_to_ptr(pContext))) {
 337         free(jlong_to_ptr(pContext));
 338     }
 339 }
 340 
 341 JNIEXPORT void JNICALL
 342 Java_sun_font_StrikeCache_getGlyphCacheDescription
 343   (JNIEnv *env, jclass cls, jlongArray results) {
 344 
 345     jlong* nresults;
 346     GlyphInfo *info;
 347     size_t baseAddr;
 348 
 349     if ((*env)->GetArrayLength(env, results) < 10) {
 350         return;
 351     }
 352 
 353     nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL);
 354     if (nresults == NULL) {
 355         return;
 356     }
 357     info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo));
 358     if (info == NULL) {
 359         (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
 360         return;
 361     }
 362     baseAddr = (size_t)info;
 363     nresults[0] = sizeof(void*);
 364     nresults[1] = sizeof(GlyphInfo);
 365     nresults[2] = 0;
 366     nresults[3] = (size_t)&(info->advanceY)-baseAddr;
 367     nresults[4] = (size_t)&(info->width)-baseAddr;
 368     nresults[5] = (size_t)&(info->height)-baseAddr;
 369     nresults[6] = (size_t)&(info->rowBytes)-baseAddr;
 370     nresults[7] = (size_t)&(info->topLeftX)-baseAddr;
 371     nresults[8] = (size_t)&(info->topLeftY)-baseAddr;
 372     nresults[9] = (size_t)&(info->image)-baseAddr;
 373     nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */
 374     (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
 375 }
 376 
 377 JNIEXPORT TTLayoutTableCache* newLayoutTableCache() {
 378   TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));
 379   if (ltc) {
 380     ltc->gsub_len = -1;
 381     ltc->gpos_len = -1;
 382     ltc->gdef_len = -1;
 383     ltc->mort_len = -1;
 384     ltc->kern_len = -1;
 385   }
 386   return ltc;
 387 }
 388 
 389 JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) {
 390   if (ltc) {
 391     if (ltc->gsub) free(ltc->gsub);
 392     if (ltc->gpos) free(ltc->gpos);
 393     if (ltc->gdef) free(ltc->gdef);
 394     if (ltc->mort) free(ltc->mort);
 395     if (ltc->kern) free(ltc->kern);
 396     if (ltc->kernPairs) free(ltc->kernPairs);
 397     free(ltc);
 398   }
 399 }