< prev index next >

src/java.desktop/share/native/libfontmanager/freetypeScaler.c

Print this page




 594     /* max advance */
 595     mx = (jfloat) FT26Dot6ToFloat(
 596                      scalerInfo->face->size->metrics.max_advance +
 597                      OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height) +
 598                      BOLD_MODIFIER(scalerInfo->face->units_per_EM,
 599                              scalerInfo->face->size->metrics.y_scale));
 600     my = 0;
 601 
 602     metrics = (*env)->NewObject(env,
 603         sunFontIDs.strikeMetricsClass,
 604         sunFontIDs.strikeMetricsCtr,
 605         contextAwareMetricsX(ax, ay), contextAwareMetricsY(ax, ay),
 606         contextAwareMetricsX(dx, dy), contextAwareMetricsY(dx, dy),
 607         bx, by,
 608         contextAwareMetricsX(lx, ly), contextAwareMetricsY(lx, ly),
 609         contextAwareMetricsX(mx, my), contextAwareMetricsY(mx, my));
 610 
 611     return metrics;
 612 }
 613 






 614 /*
 615  * Class:     sun_font_FreetypeFontScaler
 616  * Method:    getGlyphAdvanceNative
 617  * Signature: (Lsun/font/Font2D;JI)F
 618  */
 619 JNIEXPORT jfloat JNICALL
 620 Java_sun_font_FreetypeFontScaler_getGlyphAdvanceNative(
 621         JNIEnv *env, jobject scaler, jobject font2D,
 622         jlong pScalerContext, jlong pScaler, jint glyphCode) {
 623 
 624    /* This method is rarely used because requests for metrics are usually
 625       coupled with request for bitmap and to large extend work can be reused
 626       (to find out metrics we need to hint glyph).
 627       So, we typically go through getGlyphImage code path.
 628 
 629       For initial freetype implementation we delegate
 630       all work to getGlyphImage but drop result image.
 631       This is waste of work related to scan conversion and conversion from
 632       freetype format to our format but for now this seems to be ok.
 633 
 634       NB: investigate performance benefits of refactoring code
 635       to avoid unnecesary work with bitmaps. */
 636 
 637     GlyphInfo *info;
 638     jfloat advance = 0.0f;
 639     jlong image;
 640 
 641     image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
 642                  env, scaler, font2D, pScalerContext, pScaler, glyphCode);
 643     info = (GlyphInfo*) jlong_to_ptr(image);
 644 
 645     if (info != NULL) {
 646         advance = info->advanceX;
 647         free(info);
 648     }
 649 
 650     return advance;
 651 }
 652 
 653 /*
 654  * Class:     sun_font_FreetypeFontScaler
 655  * Method:    getGlyphMetricsNative
 656  * Signature: (Lsun/font/Font2D;JILjava/awt/geom/Point2D/Float;)V
 657  */
 658 JNIEXPORT void JNICALL
 659 Java_sun_font_FreetypeFontScaler_getGlyphMetricsNative(
 660         JNIEnv *env, jobject scaler, jobject font2D, jlong pScalerContext,
 661         jlong pScaler, jint glyphCode, jobject metrics) {
 662 
 663      /* As initial implementation we delegate all work to getGlyphImage
 664         but drop result image. This is clearly waste of resorces.
 665 
 666         TODO: investigate performance benefits of refactoring code
 667               by avoiding bitmap generation and conversion from FT
 668               bitmap format. */
 669      GlyphInfo *info;
 670 
 671      jlong image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
 672                                  env, scaler, font2D,
 673                                  pScalerContext, pScaler, glyphCode);
 674      info = (GlyphInfo*) jlong_to_ptr(image);
 675 
 676      if (info != NULL) {
 677          (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, info->advanceX);
 678          (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, info->advanceY);
 679          free(info);
 680      } else {
 681          (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, 0.0f);
 682          (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, 0.0f);
 683      }
 684 }
 685 
 686 
 687 static GlyphInfo* getNullGlyphImage() {
 688     GlyphInfo *glyphInfo =  (GlyphInfo*) calloc(1, sizeof(GlyphInfo));
 689     return glyphInfo;
 690 }
 691 
 692 static void CopyBW2Grey8(const void* srcImage, int srcRowBytes,
 693                          void* dstImage, int dstRowBytes,


 787 }
 788 
 789 
 790 /* JDK does not use glyph images for fonts with a
 791  * pixel size > 100 (see THRESHOLD in OutlineTextRenderer.java)
 792  * so if the glyph bitmap image dimension is > 1024 pixels,
 793  * something is up.
 794  */
 795 #define MAX_GLYPH_DIM 1024
 796 
 797 /*
 798  * Class:     sun_font_FreetypeFontScaler
 799  * Method:    getGlyphImageNative
 800  * Signature: (Lsun/font/Font2D;JI)J
 801  */
 802 JNIEXPORT jlong JNICALL
 803 Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
 804         JNIEnv *env, jobject scaler, jobject font2D,
 805         jlong pScalerContext, jlong pScaler, jint glyphCode) {
 806 











 807     int error, imageSize;
 808     UInt16 width, height;
 809     GlyphInfo *glyphInfo;
 810     int renderFlags = FT_LOAD_DEFAULT, target;
 811     FT_GlyphSlot ftglyph;
 812 
 813     FTScalerContext* context =
 814         (FTScalerContext*) jlong_to_ptr(pScalerContext);
 815     FTScalerInfo *scalerInfo =
 816              (FTScalerInfo*) jlong_to_ptr(pScaler);
 817 
 818     if (isNullScalerContext(context) || scalerInfo == NULL) {
 819         return ptr_to_jlong(getNullGlyphImage());
 820     }
 821 
 822     error = setupFTContext(env, font2D, scalerInfo, context);
 823     if (error) {
 824         invalidateJavaScaler(env, scaler, scalerInfo);
 825         return ptr_to_jlong(getNullGlyphImage());
 826     }


 849 
 850     error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags);
 851     if (error) {
 852         //do not destroy scaler yet.
 853         //this can be problem of particular context (e.g. with bad transform)
 854         return ptr_to_jlong(getNullGlyphImage());
 855     }
 856 
 857     ftglyph = scalerInfo->face->glyph;
 858 
 859     /* apply styles */
 860     if (context->doBold) { /* if bold style */
 861         FT_GlyphSlot_Embolden(ftglyph);
 862     }
 863     if (context->doItalize) { /* if oblique */
 864         FT_GlyphSlot_Oblique(ftglyph);
 865     }
 866 
 867     /* generate bitmap if it is not done yet
 868      e.g. if algorithmic styling is performed and style was added to outline */
 869     if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) {
 870         FT_BBox bbox;
 871         FT_Outline_Get_CBox(&(ftglyph->outline), &bbox);
 872         int w = (int)((bbox.xMax>>6)-(bbox.xMin>>6));
 873         int h = (int)((bbox.yMax>>6)-(bbox.yMin>>6));
 874         if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) {
 875             glyphInfo = getNullGlyphImage();
 876             return ptr_to_jlong(glyphInfo);
 877         }
 878         error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
 879         if (error != 0) {
 880             return ptr_to_jlong(getNullGlyphImage());
 881         }
 882     }
 883 

 884     width  = (UInt16) ftglyph->bitmap.width;
 885     height = (UInt16) ftglyph->bitmap.rows;
 886     if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) {
 887         glyphInfo = getNullGlyphImage();
 888         return ptr_to_jlong(glyphInfo);
 889     }




 890 
 891 
 892     imageSize = width*height;
 893     glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize);
 894     if (glyphInfo == NULL) {
 895         glyphInfo = getNullGlyphImage();
 896         return ptr_to_jlong(glyphInfo);
 897     }
 898     glyphInfo->cellInfo  = NULL;
 899     glyphInfo->managed   = UNMANAGED_GLYPH;
 900     glyphInfo->rowBytes  = width;
 901     glyphInfo->width     = width;
 902     glyphInfo->height    = height;


 903     glyphInfo->topLeftX  = (float)  ftglyph->bitmap_left;
 904     glyphInfo->topLeftY  = (float) -ftglyph->bitmap_top;
 905 
 906     if (ftglyph->bitmap.pixel_mode ==  FT_PIXEL_MODE_LCD) {
 907         glyphInfo->width = width/3;
 908     } else if (ftglyph->bitmap.pixel_mode ==  FT_PIXEL_MODE_LCD_V) {
 909         glyphInfo->height = glyphInfo->height/3;

 910     }
 911 
 912     if (context->fmType == TEXT_FM_ON) {
 913         double advh = FTFixedToFloat(ftglyph->linearHoriAdvance);
 914         glyphInfo->advanceX =
 915             (float) (advh * FTFixedToFloat(context->transform.xx));
 916         glyphInfo->advanceY =
 917             (float) (advh * FTFixedToFloat(context->transform.xy));
 918     } else {
 919         if (!ftglyph->advance.y) {
 920             glyphInfo->advanceX =
 921                 (float) FT26Dot6ToInt(ftglyph->advance.x);
 922             glyphInfo->advanceY = 0;
 923         } else if (!ftglyph->advance.x) {
 924             glyphInfo->advanceX = 0;
 925             glyphInfo->advanceY =
 926                 (float) FT26Dot6ToInt(-ftglyph->advance.y);
 927         } else {
 928             glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x);
 929             glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y);




 594     /* max advance */
 595     mx = (jfloat) FT26Dot6ToFloat(
 596                      scalerInfo->face->size->metrics.max_advance +
 597                      OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height) +
 598                      BOLD_MODIFIER(scalerInfo->face->units_per_EM,
 599                              scalerInfo->face->size->metrics.y_scale));
 600     my = 0;
 601 
 602     metrics = (*env)->NewObject(env,
 603         sunFontIDs.strikeMetricsClass,
 604         sunFontIDs.strikeMetricsCtr,
 605         contextAwareMetricsX(ax, ay), contextAwareMetricsY(ax, ay),
 606         contextAwareMetricsX(dx, dy), contextAwareMetricsY(dx, dy),
 607         bx, by,
 608         contextAwareMetricsX(lx, ly), contextAwareMetricsY(lx, ly),
 609         contextAwareMetricsX(mx, my), contextAwareMetricsY(mx, my));
 610 
 611     return metrics;
 612 }
 613 
 614 static jlong
 615     getGlyphImageNativeInternal(
 616         JNIEnv *env, jobject scaler, jobject font2D,
 617         jlong pScalerContext, jlong pScaler, jint glyphCode,
 618         jboolean renderImage);
 619 
 620 /*
 621  * Class:     sun_font_FreetypeFontScaler
 622  * Method:    getGlyphAdvanceNative
 623  * Signature: (Lsun/font/Font2D;JI)F
 624  */
 625 JNIEXPORT jfloat JNICALL
 626 Java_sun_font_FreetypeFontScaler_getGlyphAdvanceNative(
 627         JNIEnv *env, jobject scaler, jobject font2D,
 628         jlong pScalerContext, jlong pScaler, jint glyphCode) {
 629 
 630    /* This method is rarely used because requests for metrics are usually
 631     * coupled with a request for the bitmap and to a large extent the
 632     * work can be reused (to find out metrics we may need to hint the glyph).
 633     * So, we typically go through the getGlyphImage code path.
 634     * When we do get here, we need to pass a parameter which indicates
 635     * that we don't need freetype to render the bitmap, and consequently
 636     * don't need to allocate our own storage either.
 637     * This is also important when enter here requesting metrics for sizes 
 638     * of text which a large size would be rejected for a bitmap but we
 639     * still need the metrics.
 640     */

 641 
 642     GlyphInfo *info;
 643     jfloat advance = 0.0f;
 644     jlong image;
 645 
 646     image = getGlyphImageNativeInternal(
 647           env, scaler, font2D, pScalerContext, pScaler, glyphCode, JNI_FALSE);
 648     info = (GlyphInfo*) jlong_to_ptr(image);
 649 
 650     if (info != NULL) {
 651         advance = info->advanceX;
 652         free(info);
 653     }
 654 
 655     return advance;
 656 }
 657 
 658 /*
 659  * Class:     sun_font_FreetypeFontScaler
 660  * Method:    getGlyphMetricsNative
 661  * Signature: (Lsun/font/Font2D;JILjava/awt/geom/Point2D/Float;)V
 662  */
 663 JNIEXPORT void JNICALL
 664 Java_sun_font_FreetypeFontScaler_getGlyphMetricsNative(
 665         JNIEnv *env, jobject scaler, jobject font2D, jlong pScalerContext,
 666         jlong pScaler, jint glyphCode, jobject metrics) {
 667 
 668      /* See the comments in getGlyphMetricsNative. They apply here too. */





 669      GlyphInfo *info;
 670 
 671      jlong image = getGlyphImageNativeInternal(
 672                                  env, scaler, font2D,
 673                                  pScalerContext, pScaler, glyphCode, JNI_FALSE);
 674      info = (GlyphInfo*) jlong_to_ptr(image);
 675 
 676      if (info != NULL) {
 677          (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, info->advanceX);
 678          (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, info->advanceY);
 679          free(info);
 680      } else {
 681          (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, 0.0f);
 682          (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, 0.0f);
 683      }
 684 }
 685 
 686 
 687 static GlyphInfo* getNullGlyphImage() {
 688     GlyphInfo *glyphInfo =  (GlyphInfo*) calloc(1, sizeof(GlyphInfo));
 689     return glyphInfo;
 690 }
 691 
 692 static void CopyBW2Grey8(const void* srcImage, int srcRowBytes,
 693                          void* dstImage, int dstRowBytes,


 787 }
 788 
 789 
 790 /* JDK does not use glyph images for fonts with a
 791  * pixel size > 100 (see THRESHOLD in OutlineTextRenderer.java)
 792  * so if the glyph bitmap image dimension is > 1024 pixels,
 793  * something is up.
 794  */
 795 #define MAX_GLYPH_DIM 1024
 796 
 797 /*
 798  * Class:     sun_font_FreetypeFontScaler
 799  * Method:    getGlyphImageNative
 800  * Signature: (Lsun/font/Font2D;JI)J
 801  */
 802 JNIEXPORT jlong JNICALL
 803 Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
 804         JNIEnv *env, jobject scaler, jobject font2D,
 805         jlong pScalerContext, jlong pScaler, jint glyphCode) {
 806 
 807     return getGlyphImageNativeInternal(
 808         env, scaler, font2D,
 809         pScalerContext, pScaler, glyphCode, JNI_TRUE);
 810 }
 811 
 812 static jlong
 813      getGlyphImageNativeInternal(
 814         JNIEnv *env, jobject scaler, jobject font2D,
 815         jlong pScalerContext, jlong pScaler, jint glyphCode,
 816         jboolean renderImage) {
 817 
 818     int error, imageSize;
 819     UInt16 width, height;
 820     GlyphInfo *glyphInfo;
 821     int renderFlags = FT_LOAD_DEFAULT, target;
 822     FT_GlyphSlot ftglyph;
 823 
 824     FTScalerContext* context =
 825         (FTScalerContext*) jlong_to_ptr(pScalerContext);
 826     FTScalerInfo *scalerInfo =
 827              (FTScalerInfo*) jlong_to_ptr(pScaler);
 828 
 829     if (isNullScalerContext(context) || scalerInfo == NULL) {
 830         return ptr_to_jlong(getNullGlyphImage());
 831     }
 832 
 833     error = setupFTContext(env, font2D, scalerInfo, context);
 834     if (error) {
 835         invalidateJavaScaler(env, scaler, scalerInfo);
 836         return ptr_to_jlong(getNullGlyphImage());
 837     }


 860 
 861     error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags);
 862     if (error) {
 863         //do not destroy scaler yet.
 864         //this can be problem of particular context (e.g. with bad transform)
 865         return ptr_to_jlong(getNullGlyphImage());
 866     }
 867 
 868     ftglyph = scalerInfo->face->glyph;
 869 
 870     /* apply styles */
 871     if (context->doBold) { /* if bold style */
 872         FT_GlyphSlot_Embolden(ftglyph);
 873     }
 874     if (context->doItalize) { /* if oblique */
 875         FT_GlyphSlot_Oblique(ftglyph);
 876     }
 877 
 878     /* generate bitmap if it is not done yet
 879      e.g. if algorithmic styling is performed and style was added to outline */
 880     if (renderImage && (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE)) {
 881         FT_BBox bbox;
 882         FT_Outline_Get_CBox(&(ftglyph->outline), &bbox);
 883         int w = (int)((bbox.xMax>>6)-(bbox.xMin>>6));
 884         int h = (int)((bbox.yMax>>6)-(bbox.yMin>>6));
 885         if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) {
 886             glyphInfo = getNullGlyphImage();
 887             return ptr_to_jlong(glyphInfo);
 888         }
 889         error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
 890         if (error != 0) {
 891             return ptr_to_jlong(getNullGlyphImage());
 892         }
 893     }
 894 
 895     if (renderImage) {
 896         width  = (UInt16) ftglyph->bitmap.width;
 897         height = (UInt16) ftglyph->bitmap.rows;
 898             if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) {
 899               glyphInfo = getNullGlyphImage();
 900               return ptr_to_jlong(glyphInfo);
 901             }
 902      } else {
 903         width = 0;
 904         height = 0;
 905      }
 906 
 907 
 908     imageSize = width*height;
 909     glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize);
 910     if (glyphInfo == NULL) {
 911         glyphInfo = getNullGlyphImage();
 912         return ptr_to_jlong(glyphInfo);
 913     }
 914     glyphInfo->cellInfo  = NULL;
 915     glyphInfo->managed   = UNMANAGED_GLYPH;
 916     glyphInfo->rowBytes  = width;
 917     glyphInfo->width     = width;
 918     glyphInfo->height    = height;
 919 
 920     if (renderImage) {
 921         glyphInfo->topLeftX  = (float)  ftglyph->bitmap_left;
 922         glyphInfo->topLeftY  = (float) -ftglyph->bitmap_top;
 923 
 924         if (ftglyph->bitmap.pixel_mode ==  FT_PIXEL_MODE_LCD) {
 925             glyphInfo->width = width/3;
 926         } else if (ftglyph->bitmap.pixel_mode ==  FT_PIXEL_MODE_LCD_V) {
 927             glyphInfo->height = glyphInfo->height/3;
 928         }
 929     }
 930 
 931     if (context->fmType == TEXT_FM_ON) {
 932         double advh = FTFixedToFloat(ftglyph->linearHoriAdvance);
 933         glyphInfo->advanceX =
 934             (float) (advh * FTFixedToFloat(context->transform.xx));
 935         glyphInfo->advanceY =
 936             (float) (advh * FTFixedToFloat(context->transform.xy));
 937     } else {
 938         if (!ftglyph->advance.y) {
 939             glyphInfo->advanceX =
 940                 (float) FT26Dot6ToInt(ftglyph->advance.x);
 941             glyphInfo->advanceY = 0;
 942         } else if (!ftglyph->advance.x) {
 943             glyphInfo->advanceX = 0;
 944             glyphInfo->advanceY =
 945                 (float) FT26Dot6ToInt(-ftglyph->advance.y);
 946         } else {
 947             glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x);
 948             glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y);


< prev index next >