413 */ 414 context->doBold = (boldness != 1.0); 415 context->doItalize = (italic != 0); 416 417 /* freetype is very keen to use embedded bitmaps, even if it knows 418 * there is a rotation or you asked for antialiasing. 419 * In the rendering path we will check useSBits and disable 420 * bitmaps unless it is set. And here we set it only if none 421 * of the conditions invalidate using it. 422 * Note that we allow embedded bitmaps for the LCD case. 423 */ 424 if ((aa != TEXT_AA_ON) && (fm != TEXT_FM_ON) && 425 !context->doBold && !context->doItalize && 426 (context->transform.yx == 0) && (context->transform.xy == 0)) 427 { 428 context->useSbits = 1; 429 } 430 return ptr_to_jlong(context); 431 } 432 433 static int setupFTContext(JNIEnv *env, 434 jobject font2D, 435 FTScalerInfo *scalerInfo, 436 FTScalerContext *context) { 437 int errCode = 0; 438 439 scalerInfo->env = env; 440 scalerInfo->font2D = font2D; 441 442 if (context != NULL) { 443 FT_Set_Transform(scalerInfo->face, &context->transform, NULL); 444 445 errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72); 446 447 if (errCode == 0) { 448 errCode = FT_Activate_Size(scalerInfo->face->size); 449 } 450 451 FT_Library_SetLcdFilter(scalerInfo->library, FT_LCD_FILTER_DEFAULT); 452 } 453 454 return errCode; 455 } 456 457 /* ftsynth.c uses (0x10000, 0x0366A, 0x0, 0x10000) matrix to get oblique 458 outline. Therefore x coordinate will change by 0x0366A*y. 459 Note that y coordinate does not change. These values are based on 460 libfreetype version 2.9.1. */ 461 #define OBLIQUE_MODIFIER(y) (context->doItalize ? ((y)*0x366A/0x10000) : 0) 462 463 /* FT_GlyphSlot_Embolden (ftsynth.c) uses FT_MulFix(units_per_EM, y_scale) / 24 464 * strength value when glyph format is FT_GLYPH_FORMAT_OUTLINE. This value has 465 * been taken from libfreetype version 2.6 and remain valid at least up to 466 * 2.9.1. */ 467 #define BOLD_MODIFIER(units_per_EM, y_scale) \ 468 (context->doBold ? FT_MulFix(units_per_EM, y_scale) / 24 : 0) 469 470 /* 471 * Class: sun_font_FreetypeFontScaler 472 * Method: getFontMetricsNative 473 * Signature: (Lsun/font/Font2D;J)Lsun/font/StrikeMetrics; 474 */ 475 JNIEXPORT jobject JNICALL 476 Java_sun_font_FreetypeFontScaler_getFontMetricsNative( 477 JNIEnv *env, jobject scaler, jobject font2D, 478 jlong pScalerContext, jlong pScaler) { 479 480 jobject metrics; 481 jfloat ax, ay, dx, dy, bx, by, lx, ly, mx, my; 789 context->aaType == TEXT_AA_LCD_HBGR) { 790 target = FT_LOAD_TARGET_LCD; 791 } else { 792 target = FT_LOAD_TARGET_LCD_V; 793 } 794 renderFlags |= target; 795 796 error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); 797 if (error) { 798 //do not destroy scaler yet. 799 //this can be problem of particular context (e.g. with bad transform) 800 return ptr_to_jlong(getNullGlyphImage()); 801 } 802 803 ftglyph = scalerInfo->face->glyph; 804 805 /* apply styles */ 806 if (context->doBold) { /* if bold style */ 807 FT_GlyphSlot_Embolden(ftglyph); 808 } 809 if (context->doItalize) { /* if oblique */ 810 FT_GlyphSlot_Oblique(ftglyph); 811 } 812 813 /* generate bitmap if it is not done yet 814 e.g. if algorithmic styling is performed and style was added to outline */ 815 if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) { 816 error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target)); 817 if (error != 0) { 818 return ptr_to_jlong(getNullGlyphImage()); 819 } 820 } 821 822 width = (UInt16) ftglyph->bitmap.width; 823 height = (UInt16) ftglyph->bitmap.rows; 824 825 imageSize = width*height; 826 glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize); 827 if (glyphInfo == NULL) { 828 glyphInfo = getNullGlyphImage(); 829 return ptr_to_jlong(glyphInfo); 830 } 831 glyphInfo->cellInfo = NULL; 1014 return NULL; 1015 } 1016 1017 error = setupFTContext(env, font2D, scalerInfo, context); 1018 if (error) { 1019 return NULL; 1020 } 1021 1022 renderFlags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; 1023 1024 error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); 1025 if (error) { 1026 return NULL; 1027 } 1028 1029 ftglyph = scalerInfo->face->glyph; 1030 1031 /* apply styles */ 1032 if (context->doBold) { /* if bold style */ 1033 FT_GlyphSlot_Embolden(ftglyph); 1034 } 1035 if (context->doItalize) { /* if oblique */ 1036 FT_GlyphSlot_Oblique(ftglyph); 1037 } 1038 1039 FT_Outline_Translate(&ftglyph->outline, 1040 FloatToF26Dot6(xpos), 1041 -FloatToF26Dot6(ypos)); 1042 1043 return &ftglyph->outline; 1044 } 1045 1046 #define F26Dot6ToFloat(n) (((float)(n))/((float) 64)) 1047 1048 /* Types of GeneralPath segments. 1049 TODO: pull constants from other place? */ 1050 1051 #define SEG_UNKNOWN -1 1052 #define SEG_MOVETO 0 1053 #define SEG_LINETO 1 1054 #define SEG_QUADTO 2 1055 #define SEG_CUBICTO 3 1056 #define SEG_CLOSE 4 | 413 */ 414 context->doBold = (boldness != 1.0); 415 context->doItalize = (italic != 0); 416 417 /* freetype is very keen to use embedded bitmaps, even if it knows 418 * there is a rotation or you asked for antialiasing. 419 * In the rendering path we will check useSBits and disable 420 * bitmaps unless it is set. And here we set it only if none 421 * of the conditions invalidate using it. 422 * Note that we allow embedded bitmaps for the LCD case. 423 */ 424 if ((aa != TEXT_AA_ON) && (fm != TEXT_FM_ON) && 425 !context->doBold && !context->doItalize && 426 (context->transform.yx == 0) && (context->transform.xy == 0)) 427 { 428 context->useSbits = 1; 429 } 430 return ptr_to_jlong(context); 431 } 432 433 // values used by FreeType (as of version 2.10.1) for italics transformation matrix in FT_GlyphSlot_Oblique 434 #define FT_MATRIX_ONE 0x10000 435 #define FT_MATRIX_OBLIQUE_XY 0x0366A 436 437 static void setupTransform(FT_Matrix* target, FTScalerContext *context) { 438 FT_Matrix* transform = &context->transform; 439 if (context->doItalize) { 440 // we cannot use FT_GlyphSlot_Oblique as it doesn't work well with arbitrary transforms, 441 // so we add corresponding shear transform to the requested glyph transformation 442 target->xx = FT_MATRIX_ONE; 443 target->xy = FT_MATRIX_OBLIQUE_XY; 444 target->yx = 0; 445 target->yy = FT_MATRIX_ONE; 446 FT_Matrix_Multiply(transform, target); 447 } else { 448 target->xx = transform->xx; 449 target->xy = transform->xy; 450 target->yx = transform->yx; 451 target->yy = transform->yy; 452 } 453 } 454 455 static int setupFTContext(JNIEnv *env, 456 jobject font2D, 457 FTScalerInfo *scalerInfo, 458 FTScalerContext *context) { 459 FT_Matrix matrix; 460 int errCode = 0; 461 462 scalerInfo->env = env; 463 scalerInfo->font2D = font2D; 464 465 if (context != NULL) { 466 setupTransform(&matrix, context); 467 FT_Set_Transform(scalerInfo->face, &matrix, NULL); 468 469 errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72); 470 471 if (errCode == 0) { 472 errCode = FT_Activate_Size(scalerInfo->face->size); 473 } 474 475 FT_Library_SetLcdFilter(scalerInfo->library, FT_LCD_FILTER_DEFAULT); 476 } 477 478 return errCode; 479 } 480 481 // using same values as for the transformation matrix 482 #define OBLIQUE_MODIFIER(y) (context->doItalize ? ((y)*FT_MATRIX_OBLIQUE_XY/FT_MATRIX_ONE) : 0) 483 484 /* FT_GlyphSlot_Embolden (ftsynth.c) uses FT_MulFix(units_per_EM, y_scale) / 24 485 * strength value when glyph format is FT_GLYPH_FORMAT_OUTLINE. This value has 486 * been taken from libfreetype version 2.6 and remain valid at least up to 487 * 2.9.1. */ 488 #define BOLD_MODIFIER(units_per_EM, y_scale) \ 489 (context->doBold ? FT_MulFix(units_per_EM, y_scale) / 24 : 0) 490 491 /* 492 * Class: sun_font_FreetypeFontScaler 493 * Method: getFontMetricsNative 494 * Signature: (Lsun/font/Font2D;J)Lsun/font/StrikeMetrics; 495 */ 496 JNIEXPORT jobject JNICALL 497 Java_sun_font_FreetypeFontScaler_getFontMetricsNative( 498 JNIEnv *env, jobject scaler, jobject font2D, 499 jlong pScalerContext, jlong pScaler) { 500 501 jobject metrics; 502 jfloat ax, ay, dx, dy, bx, by, lx, ly, mx, my; 810 context->aaType == TEXT_AA_LCD_HBGR) { 811 target = FT_LOAD_TARGET_LCD; 812 } else { 813 target = FT_LOAD_TARGET_LCD_V; 814 } 815 renderFlags |= target; 816 817 error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); 818 if (error) { 819 //do not destroy scaler yet. 820 //this can be problem of particular context (e.g. with bad transform) 821 return ptr_to_jlong(getNullGlyphImage()); 822 } 823 824 ftglyph = scalerInfo->face->glyph; 825 826 /* apply styles */ 827 if (context->doBold) { /* if bold style */ 828 FT_GlyphSlot_Embolden(ftglyph); 829 } 830 831 /* generate bitmap if it is not done yet 832 e.g. if algorithmic styling is performed and style was added to outline */ 833 if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) { 834 error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target)); 835 if (error != 0) { 836 return ptr_to_jlong(getNullGlyphImage()); 837 } 838 } 839 840 width = (UInt16) ftglyph->bitmap.width; 841 height = (UInt16) ftglyph->bitmap.rows; 842 843 imageSize = width*height; 844 glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize); 845 if (glyphInfo == NULL) { 846 glyphInfo = getNullGlyphImage(); 847 return ptr_to_jlong(glyphInfo); 848 } 849 glyphInfo->cellInfo = NULL; 1032 return NULL; 1033 } 1034 1035 error = setupFTContext(env, font2D, scalerInfo, context); 1036 if (error) { 1037 return NULL; 1038 } 1039 1040 renderFlags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; 1041 1042 error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); 1043 if (error) { 1044 return NULL; 1045 } 1046 1047 ftglyph = scalerInfo->face->glyph; 1048 1049 /* apply styles */ 1050 if (context->doBold) { /* if bold style */ 1051 FT_GlyphSlot_Embolden(ftglyph); 1052 } 1053 1054 FT_Outline_Translate(&ftglyph->outline, 1055 FloatToF26Dot6(xpos), 1056 -FloatToF26Dot6(ypos)); 1057 1058 return &ftglyph->outline; 1059 } 1060 1061 #define F26Dot6ToFloat(n) (((float)(n))/((float) 64)) 1062 1063 /* Types of GeneralPath segments. 1064 TODO: pull constants from other place? */ 1065 1066 #define SEG_UNKNOWN -1 1067 #define SEG_MOVETO 0 1068 #define SEG_LINETO 1 1069 #define SEG_QUADTO 2 1070 #define SEG_CUBICTO 3 1071 #define SEG_CLOSE 4 |