1 /*
   2  * Copyright (c) 2007, 2010, 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 }