609 contextAwareMetricsX(mx, my), contextAwareMetricsY(mx, my)); |
609 contextAwareMetricsX(mx, my), contextAwareMetricsY(mx, my)); |
610 |
610 |
611 return metrics; |
611 return metrics; |
612 } |
612 } |
613 |
613 |
|
614 static jlong |
|
615 getGlyphImageNativeInternal( |
|
616 JNIEnv *env, jobject scaler, jobject font2D, |
|
617 jlong pScalerContext, jlong pScaler, jint glyphCode, |
|
618 jboolean renderImage); |
|
619 |
614 /* |
620 /* |
615 * Class: sun_font_FreetypeFontScaler |
621 * Class: sun_font_FreetypeFontScaler |
616 * Method: getGlyphAdvanceNative |
622 * Method: getGlyphAdvanceNative |
617 * Signature: (Lsun/font/Font2D;JI)F |
623 * Signature: (Lsun/font/Font2D;JI)F |
618 */ |
624 */ |
620 Java_sun_font_FreetypeFontScaler_getGlyphAdvanceNative( |
626 Java_sun_font_FreetypeFontScaler_getGlyphAdvanceNative( |
621 JNIEnv *env, jobject scaler, jobject font2D, |
627 JNIEnv *env, jobject scaler, jobject font2D, |
622 jlong pScalerContext, jlong pScaler, jint glyphCode) { |
628 jlong pScalerContext, jlong pScaler, jint glyphCode) { |
623 |
629 |
624 /* This method is rarely used because requests for metrics are usually |
630 /* 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 |
631 * coupled with a request for the bitmap and to a large extent the |
626 (to find out metrics we need to hint glyph). |
632 * work can be reused (to find out metrics we may need to hint the glyph). |
627 So, we typically go through getGlyphImage code path. |
633 * So, we typically go through the getGlyphImage code path. |
628 |
634 * When we do get here, we need to pass a parameter which indicates |
629 For initial freetype implementation we delegate |
635 * that we don't need freetype to render the bitmap, and consequently |
630 all work to getGlyphImage but drop result image. |
636 * don't need to allocate our own storage either. |
631 This is waste of work related to scan conversion and conversion from |
637 * This is also important when enter here requesting metrics for sizes |
632 freetype format to our format but for now this seems to be ok. |
638 * of text which a large size would be rejected for a bitmap but we |
633 |
639 * still need the metrics. |
634 NB: investigate performance benefits of refactoring code |
640 */ |
635 to avoid unnecesary work with bitmaps. */ |
|
636 |
641 |
637 GlyphInfo *info; |
642 GlyphInfo *info; |
638 jfloat advance = 0.0f; |
643 jfloat advance = 0.0f; |
639 jlong image; |
644 jlong image; |
640 |
645 |
641 image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative( |
646 image = getGlyphImageNativeInternal( |
642 env, scaler, font2D, pScalerContext, pScaler, glyphCode); |
647 env, scaler, font2D, pScalerContext, pScaler, glyphCode, JNI_FALSE); |
643 info = (GlyphInfo*) jlong_to_ptr(image); |
648 info = (GlyphInfo*) jlong_to_ptr(image); |
644 |
649 |
645 if (info != NULL) { |
650 if (info != NULL) { |
646 advance = info->advanceX; |
651 advance = info->advanceX; |
647 free(info); |
652 free(info); |
658 JNIEXPORT void JNICALL |
663 JNIEXPORT void JNICALL |
659 Java_sun_font_FreetypeFontScaler_getGlyphMetricsNative( |
664 Java_sun_font_FreetypeFontScaler_getGlyphMetricsNative( |
660 JNIEnv *env, jobject scaler, jobject font2D, jlong pScalerContext, |
665 JNIEnv *env, jobject scaler, jobject font2D, jlong pScalerContext, |
661 jlong pScaler, jint glyphCode, jobject metrics) { |
666 jlong pScaler, jint glyphCode, jobject metrics) { |
662 |
667 |
663 /* As initial implementation we delegate all work to getGlyphImage |
668 /* See the comments in getGlyphMetricsNative. They apply here too. */ |
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; |
669 GlyphInfo *info; |
670 |
670 |
671 jlong image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative( |
671 jlong image = getGlyphImageNativeInternal( |
672 env, scaler, font2D, |
672 env, scaler, font2D, |
673 pScalerContext, pScaler, glyphCode); |
673 pScalerContext, pScaler, glyphCode, JNI_FALSE); |
674 info = (GlyphInfo*) jlong_to_ptr(image); |
674 info = (GlyphInfo*) jlong_to_ptr(image); |
675 |
675 |
676 if (info != NULL) { |
676 if (info != NULL) { |
677 (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, info->advanceX); |
677 (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, info->advanceX); |
678 (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, info->advanceY); |
678 (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, info->advanceY); |
801 */ |
801 */ |
802 JNIEXPORT jlong JNICALL |
802 JNIEXPORT jlong JNICALL |
803 Java_sun_font_FreetypeFontScaler_getGlyphImageNative( |
803 Java_sun_font_FreetypeFontScaler_getGlyphImageNative( |
804 JNIEnv *env, jobject scaler, jobject font2D, |
804 JNIEnv *env, jobject scaler, jobject font2D, |
805 jlong pScalerContext, jlong pScaler, jint glyphCode) { |
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) { |
806 |
817 |
807 int error, imageSize; |
818 int error, imageSize; |
808 UInt16 width, height; |
819 UInt16 width, height; |
809 GlyphInfo *glyphInfo; |
820 GlyphInfo *glyphInfo; |
810 int renderFlags = FT_LOAD_DEFAULT, target; |
821 int renderFlags = FT_LOAD_DEFAULT, target; |
864 FT_GlyphSlot_Oblique(ftglyph); |
875 FT_GlyphSlot_Oblique(ftglyph); |
865 } |
876 } |
866 |
877 |
867 /* generate bitmap if it is not done yet |
878 /* generate bitmap if it is not done yet |
868 e.g. if algorithmic styling is performed and style was added to outline */ |
879 e.g. if algorithmic styling is performed and style was added to outline */ |
869 if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) { |
880 if (renderImage && (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE)) { |
870 FT_BBox bbox; |
881 FT_BBox bbox; |
871 FT_Outline_Get_CBox(&(ftglyph->outline), &bbox); |
882 FT_Outline_Get_CBox(&(ftglyph->outline), &bbox); |
872 int w = (int)((bbox.xMax>>6)-(bbox.xMin>>6)); |
883 int w = (int)((bbox.xMax>>6)-(bbox.xMin>>6)); |
873 int h = (int)((bbox.yMax>>6)-(bbox.yMin>>6)); |
884 int h = (int)((bbox.yMax>>6)-(bbox.yMin>>6)); |
874 if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) { |
885 if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) { |
879 if (error != 0) { |
890 if (error != 0) { |
880 return ptr_to_jlong(getNullGlyphImage()); |
891 return ptr_to_jlong(getNullGlyphImage()); |
881 } |
892 } |
882 } |
893 } |
883 |
894 |
884 width = (UInt16) ftglyph->bitmap.width; |
895 if (renderImage) { |
885 height = (UInt16) ftglyph->bitmap.rows; |
896 width = (UInt16) ftglyph->bitmap.width; |
886 if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) { |
897 height = (UInt16) ftglyph->bitmap.rows; |
887 glyphInfo = getNullGlyphImage(); |
898 if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) { |
888 return ptr_to_jlong(glyphInfo); |
899 glyphInfo = getNullGlyphImage(); |
889 } |
900 return ptr_to_jlong(glyphInfo); |
|
901 } |
|
902 } else { |
|
903 width = 0; |
|
904 height = 0; |
|
905 } |
890 |
906 |
891 |
907 |
892 imageSize = width*height; |
908 imageSize = width*height; |
893 glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize); |
909 glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize); |
894 if (glyphInfo == NULL) { |
910 if (glyphInfo == NULL) { |
898 glyphInfo->cellInfo = NULL; |
914 glyphInfo->cellInfo = NULL; |
899 glyphInfo->managed = UNMANAGED_GLYPH; |
915 glyphInfo->managed = UNMANAGED_GLYPH; |
900 glyphInfo->rowBytes = width; |
916 glyphInfo->rowBytes = width; |
901 glyphInfo->width = width; |
917 glyphInfo->width = width; |
902 glyphInfo->height = height; |
918 glyphInfo->height = height; |
903 glyphInfo->topLeftX = (float) ftglyph->bitmap_left; |
919 |
904 glyphInfo->topLeftY = (float) -ftglyph->bitmap_top; |
920 if (renderImage) { |
905 |
921 glyphInfo->topLeftX = (float) ftglyph->bitmap_left; |
906 if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) { |
922 glyphInfo->topLeftY = (float) -ftglyph->bitmap_top; |
907 glyphInfo->width = width/3; |
923 |
908 } else if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) { |
924 if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) { |
909 glyphInfo->height = glyphInfo->height/3; |
925 glyphInfo->width = width/3; |
|
926 } else if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) { |
|
927 glyphInfo->height = glyphInfo->height/3; |
|
928 } |
910 } |
929 } |
911 |
930 |
912 if (context->fmType == TEXT_FM_ON) { |
931 if (context->fmType == TEXT_FM_ON) { |
913 double advh = FTFixedToFloat(ftglyph->linearHoriAdvance); |
932 double advh = FTFixedToFloat(ftglyph->linearHoriAdvance); |
914 glyphInfo->advanceX = |
933 glyphInfo->advanceX = |