src/java.desktop/share/native/libfontmanager/freetypeScaler.c
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54590 98473958d49a
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    27 #include "jni_util.h"
    27 #include "jni_util.h"
    28 #include "jlong.h"
    28 #include "jlong.h"
    29 #include "sunfontids.h"
    29 #include "sunfontids.h"
    30 #include "sun_font_FreetypeFontScaler.h"
    30 #include "sun_font_FreetypeFontScaler.h"
    31 
    31 
    32 #include<stdlib.h>
    32 #include <stdlib.h>
       
    33 #if !defined(_WIN32) && !defined(__APPLE_)
       
    34 #include <dlfcn.h>
       
    35 #endif
    33 #include <math.h>
    36 #include <math.h>
    34 #include "ft2build.h"
    37 #include "ft2build.h"
    35 #include FT_FREETYPE_H
    38 #include FT_FREETYPE_H
    36 #include FT_GLYPH_H
    39 #include FT_GLYPH_H
    37 #include FT_BBOX_H
    40 #include FT_BBOX_H
    38 #include FT_SIZES_H
    41 #include FT_SIZES_H
    39 #include FT_OUTLINE_H
    42 #include FT_OUTLINE_H
    40 #include FT_SYNTHESIS_H
    43 #include FT_SYNTHESIS_H
    41 #include FT_LCD_FILTER_H
    44 #include FT_LCD_FILTER_H
       
    45 #include FT_MODULE_H
    42 
    46 
    43 #include "fontscaler.h"
    47 #include "fontscaler.h"
    44 
    48 
    45 #define  ftFixed1  (FT_Fixed) (1 << 16)
    49 #define  ftFixed1  (FT_Fixed) (1 << 16)
    46 #define  FloatToFTFixed(f) (FT_Fixed)((f) * (float)(ftFixed1))
    50 #define  FloatToFTFixed(f) (FT_Fixed)((f) * (float)(ftFixed1))
   148     FTScalerInfo *scalerInfo = (FTScalerInfo *) stream->pathname.pointer;
   152     FTScalerInfo *scalerInfo = (FTScalerInfo *) stream->pathname.pointer;
   149     JNIEnv* env = scalerInfo->env;
   153     JNIEnv* env = scalerInfo->env;
   150     jobject bBuffer;
   154     jobject bBuffer;
   151     int bread = 0;
   155     int bread = 0;
   152 
   156 
   153     if (numBytes == 0) return 0;
   157     /* A call with numBytes == 0 is a seek. It should return 0 if the
       
   158      * seek position is within the file and non-zero otherwise.
       
   159      * For all other cases, ie numBytes !=0, return the number of bytes
       
   160      * actually read. This applies to truncated reads and also failed reads.
       
   161      */
       
   162 
       
   163     if (numBytes == 0) {
       
   164         if (offset > scalerInfo->fileSize) {
       
   165             return -1;
       
   166         } else {
       
   167             return 0;
       
   168        }
       
   169     }
       
   170 
       
   171     if (offset + numBytes < offset) {
       
   172         return 0; // ft should not do this, but just in case.
       
   173     }
       
   174 
       
   175     if (offset >= scalerInfo->fileSize) {
       
   176         return 0;
       
   177     }
       
   178 
       
   179     if (offset + numBytes > scalerInfo->fileSize) {
       
   180         numBytes = scalerInfo->fileSize - offset;
       
   181     }
   154 
   182 
   155     /* Large reads will bypass the cache and data copying */
   183     /* Large reads will bypass the cache and data copying */
   156     if (numBytes > FILEDATACACHESIZE) {
   184     if (numBytes > FILEDATACACHESIZE) {
   157         bBuffer = (*env)->NewDirectByteBuffer(env, destBuffer, numBytes);
   185         bBuffer = (*env)->NewDirectByteBuffer(env, destBuffer, numBytes);
   158         if (bBuffer != NULL) {
   186         if (bBuffer != NULL) {
   159             bread = (*env)->CallIntMethod(env,
   187             bread = (*env)->CallIntMethod(env,
   160                                           scalerInfo->font2D,
   188                                           scalerInfo->font2D,
   161                                           sunFontIDs.ttReadBlockMID,
   189                                           sunFontIDs.ttReadBlockMID,
   162                                           bBuffer, offset, numBytes);
   190                                           bBuffer, offset, numBytes);
   163             return bread;
   191             if (bread < 0) {
       
   192                 return 0;
       
   193             } else {
       
   194                return bread;
       
   195             }
   164         } else {
   196         } else {
   165             /* We probably hit bug 4845371. For reasons that
   197             /* We probably hit bug 4845371. For reasons that
   166              * are currently unclear, the call stacks after the initial
   198              * are currently unclear, the call stacks after the initial
   167              * createScaler call that read large amounts of data seem to
   199              * createScaler call that read large amounts of data seem to
   168              * be OK and can create the byte buffer above, but this code
   200              * be OK and can create the byte buffer above, but this code
   173              */
   205              */
   174             jbyteArray byteArray = (jbyteArray)
   206             jbyteArray byteArray = (jbyteArray)
   175             (*env)->CallObjectMethod(env, scalerInfo->font2D,
   207             (*env)->CallObjectMethod(env, scalerInfo->font2D,
   176                                      sunFontIDs.ttReadBytesMID,
   208                                      sunFontIDs.ttReadBytesMID,
   177                                      offset, numBytes);
   209                                      offset, numBytes);
   178             (*env)->GetByteArrayRegion(env, byteArray,
   210             /* If there's an OutofMemoryError then byteArray will be null */
   179                                        0, numBytes, (jbyte*)destBuffer);
   211             if (byteArray == NULL) {
   180             return numBytes;
   212                 return 0;
       
   213             } else {
       
   214                 jsize len = (*env)->GetArrayLength(env, byteArray);
       
   215                 if (len < numBytes) {
       
   216                     numBytes = len; // don't get more bytes than there are ..
       
   217                 }
       
   218                 (*env)->GetByteArrayRegion(env, byteArray,
       
   219                                            0, numBytes, (jbyte*)destBuffer);
       
   220                 return numBytes;
       
   221             }
   181         }
   222         }
   182     } /* Do we have a cache hit? */
   223     } /* Do we have a cache hit? */
   183       else if (scalerInfo->fontDataOffset <= offset &&
   224       else if (scalerInfo->fontDataOffset <= offset &&
   184         scalerInfo->fontDataOffset + scalerInfo->fontDataLength >=
   225         scalerInfo->fontDataOffset + scalerInfo->fontDataLength >=
   185                                                          offset + numBytes)
   226                                                          offset + numBytes)
   197         bBuffer = scalerInfo->directBuffer;
   238         bBuffer = scalerInfo->directBuffer;
   198         bread = (*env)->CallIntMethod(env, scalerInfo->font2D,
   239         bread = (*env)->CallIntMethod(env, scalerInfo->font2D,
   199                                       sunFontIDs.ttReadBlockMID,
   240                                       sunFontIDs.ttReadBlockMID,
   200                                       bBuffer, offset,
   241                                       bBuffer, offset,
   201                                       scalerInfo->fontDataLength);
   242                                       scalerInfo->fontDataLength);
       
   243         if (bread <= 0) {
       
   244             return 0;
       
   245         } else if (bread < numBytes) {
       
   246            numBytes = bread;
       
   247         }
   202         memcpy(destBuffer, scalerInfo->fontData, numBytes);
   248         memcpy(destBuffer, scalerInfo->fontData, numBytes);
   203         return numBytes;
   249         return numBytes;
   204     }
   250     }
       
   251 }
       
   252 
       
   253 typedef FT_Error (*FT_Prop_Set_Func)(FT_Library library,
       
   254                                      const FT_String*  module_name,
       
   255                                      const FT_String*  property_name,
       
   256                                      const void*       value );
       
   257 
       
   258 /**
       
   259  * Prefer the older v35 freetype byte code interpreter.
       
   260  */
       
   261 static void setInterpreterVersion(FT_Library library) {
       
   262 
       
   263     char* props = getenv("FREETYPE_PROPERTIES");
       
   264     int version = 35;
       
   265     const char* module = "truetype";
       
   266     const char* property = "interpreter-version";
       
   267 
       
   268     /* If some one is setting this, don't override it */
       
   269     if (props != NULL && strstr(property, props)) {
       
   270         return;
       
   271     }
       
   272     /*
       
   273      * FT_Property_Set was introduced in 2.4.11.
       
   274      * Some older supported Linux OSes may not include it so look
       
   275      * this up dynamically.
       
   276      * And if its not available it doesn't matter, since the reason
       
   277      * we need it dates from 2.7.
       
   278      * On Windows & Mac the library is always bundled so it is safe
       
   279      * to use directly in those cases.
       
   280      */
       
   281 #if defined(_WIN32) || defined(__APPLE__)
       
   282     FT_Property_Set(library, module, property, (void*)(&version));
       
   283 #else
       
   284     void *lib = dlopen("libfreetype.so", RTLD_LOCAL|RTLD_LAZY);
       
   285     if (lib == NULL) {
       
   286         lib = dlopen("libfreetype.so.6", RTLD_LOCAL|RTLD_LAZY);
       
   287         if (lib == NULL) {
       
   288             return;
       
   289         }
       
   290     }
       
   291     FT_Prop_Set_Func func = (FT_Prop_Set_Func)dlsym(lib, "FT_Property_Set");
       
   292     if (func != NULL) {
       
   293         func(library, module, property, (void*)(&version));
       
   294     }
       
   295     dlclose(lib);
       
   296 #endif
   205 }
   297 }
   206 
   298 
   207 /*
   299 /*
   208  * Class:     sun_font_FreetypeFontScaler
   300  * Class:     sun_font_FreetypeFontScaler
   209  * Method:    initNativeScaler
   301  * Method:    initNativeScaler
   241     error = FT_Init_FreeType(&scalerInfo->library);
   333     error = FT_Init_FreeType(&scalerInfo->library);
   242     if (error) {
   334     if (error) {
   243         free(scalerInfo);
   335         free(scalerInfo);
   244         return 0;
   336         return 0;
   245     }
   337     }
       
   338     setInterpreterVersion(scalerInfo->library);
   246 
   339 
   247 #define TYPE1_FROM_JAVA        2
   340 #define TYPE1_FROM_JAVA        2
   248 
   341 
   249     error = 1; /* triggers memory freeing unless we clear it */
   342     error = 1; /* triggers memory freeing unless we clear it */
   250     if (type == TYPE1_FROM_JAVA) { /* TYPE1 */
   343     if (type == TYPE1_FROM_JAVA) { /* TYPE1 */
   540 
   633 
   541       NB: investigate performance benefits of refactoring code
   634       NB: investigate performance benefits of refactoring code
   542       to avoid unnecesary work with bitmaps. */
   635       to avoid unnecesary work with bitmaps. */
   543 
   636 
   544     GlyphInfo *info;
   637     GlyphInfo *info;
   545     jfloat advance;
   638     jfloat advance = 0.0f;
   546     jlong image;
   639     jlong image;
   547 
   640 
   548     image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
   641     image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
   549                  env, scaler, font2D, pScalerContext, pScaler, glyphCode);
   642                  env, scaler, font2D, pScalerContext, pScaler, glyphCode);
   550     info = (GlyphInfo*) jlong_to_ptr(image);
   643     info = (GlyphInfo*) jlong_to_ptr(image);
   551 
   644 
   552     advance = info->advanceX;
   645     if (info != NULL) {
   553 
   646         advance = info->advanceX;
   554     free(info);
   647         free(info);
       
   648     }
   555 
   649 
   556     return advance;
   650     return advance;
   557 }
   651 }
   558 
   652 
   559 /*
   653 /*
   686         dstRow += dstRowBytes;
   780         dstRow += dstRowBytes;
   687         height -= 3;
   781         height -= 3;
   688     }
   782     }
   689 }
   783 }
   690 
   784 
       
   785 
       
   786 /* JDK does not use glyph images for fonts with a
       
   787  * pixel size > 100 (see THRESHOLD in OutlineTextRenderer.java)
       
   788  * so if the glyph bitmap image dimension is > 1024 pixels,
       
   789  * something is up.
       
   790  */
       
   791 #define MAX_GLYPH_DIM 1024
   691 
   792 
   692 /*
   793 /*
   693  * Class:     sun_font_FreetypeFontScaler
   794  * Class:     sun_font_FreetypeFontScaler
   694  * Method:    getGlyphImageNative
   795  * Method:    getGlyphImageNative
   695  * Signature: (Lsun/font/Font2D;JI)J
   796  * Signature: (Lsun/font/Font2D;JI)J
   760     }
   861     }
   761 
   862 
   762     /* generate bitmap if it is not done yet
   863     /* generate bitmap if it is not done yet
   763      e.g. if algorithmic styling is performed and style was added to outline */
   864      e.g. if algorithmic styling is performed and style was added to outline */
   764     if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) {
   865     if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) {
       
   866         FT_BBox bbox;
       
   867         FT_Outline_Get_CBox(&(ftglyph->outline), &bbox);
       
   868         int w = (int)((bbox.xMax>>6)-(bbox.xMin>>6));
       
   869         int h = (int)((bbox.yMax>>6)-(bbox.yMin>>6));
       
   870         if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) {
       
   871             glyphInfo = getNullGlyphImage();
       
   872             return ptr_to_jlong(glyphInfo);
       
   873         }
   765         error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
   874         error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
   766         if (error != 0) {
   875         if (error != 0) {
   767             return ptr_to_jlong(getNullGlyphImage());
   876             return ptr_to_jlong(getNullGlyphImage());
   768         }
   877         }
   769     }
   878     }
   770 
   879 
   771     width  = (UInt16) ftglyph->bitmap.width;
   880     width  = (UInt16) ftglyph->bitmap.width;
   772     height = (UInt16) ftglyph->bitmap.rows;
   881     height = (UInt16) ftglyph->bitmap.rows;
       
   882     if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) {
       
   883         glyphInfo = getNullGlyphImage();
       
   884         return ptr_to_jlong(glyphInfo);
       
   885     }
       
   886 
   773 
   887 
   774     imageSize = width*height;
   888     imageSize = width*height;
   775     glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize);
   889     glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize);
   776     if (glyphInfo == NULL) {
   890     if (glyphInfo == NULL) {
   777         glyphInfo = getNullGlyphImage();
   891         glyphInfo = getNullGlyphImage();