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