Lines 38-43
Link Here
|
38 |
#include FT_SIZES_H |
38 |
#include FT_SIZES_H |
39 |
#include FT_OUTLINE_H |
39 |
#include FT_OUTLINE_H |
40 |
#include FT_SYNTHESIS_H |
40 |
#include FT_SYNTHESIS_H |
|
|
41 |
#include FT_LCD_FILTER_H |
42 |
#include <fontconfig/fontconfig.h> |
41 |
|
43 |
|
42 |
#include "fontscaler.h" |
44 |
#include "fontscaler.h" |
43 |
|
45 |
|
Lines 665-671
Link Here
|
665 |
} |
667 |
} |
666 |
} |
668 |
} |
667 |
|
669 |
|
|
|
670 |
typedef struct { |
671 |
FT_Render_Mode ftRenderMode; |
672 |
int ftLoadFlags; |
673 |
FT_LcdFilter ftLcdFilter; |
674 |
} RenderingProperties; |
668 |
|
675 |
|
|
|
676 |
static FcPattern* matchedPattern(const FcChar8* family, double ptSize) { |
677 |
FcPattern* pattern = FcPatternCreate(); |
678 |
if (!pattern) |
679 |
return 0; |
680 |
|
681 |
FcPatternAddString(pattern, FC_FAMILY, family); |
682 |
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
683 |
FcPatternAddDouble(pattern, FC_SIZE, ptSize); |
684 |
|
685 |
FcConfigSubstitute(0, pattern, FcMatchPattern); |
686 |
FcDefaultSubstitute(pattern); |
687 |
|
688 |
FcResult res; |
689 |
FcPattern *match = FcFontMatch(0, pattern, &res); |
690 |
FcPatternDestroy(pattern); |
691 |
return (res == FcResultMatch) ? match : NULL; |
692 |
} |
693 |
|
694 |
static void readFontconfig(const FcChar8* family, double ptSize, jint aaType, RenderingProperties* rp) { |
695 |
FcPattern *pattern = matchedPattern(family, ptSize); |
696 |
|
697 |
FT_Render_Mode ftRenderMode = FT_RENDER_MODE_NORMAL; |
698 |
int ftLoadFlags = FT_LOAD_DEFAULT; |
699 |
FT_LcdFilter ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
700 |
FcBool fcAntialias = 0; |
701 |
char horizontal = 1; |
702 |
|
703 |
// subpixel order |
704 |
if (aaType == TEXT_AA_ON) |
705 |
ftRenderMode = FT_RENDER_MODE_NORMAL; |
706 |
else if (aaType == TEXT_AA_OFF) |
707 |
ftRenderMode = FT_RENDER_MODE_MONO; |
708 |
else { |
709 |
int fcRGBA = FC_RGBA_UNKNOWN; |
710 |
if (pattern) |
711 |
FcPatternGetInteger(pattern, FC_RGBA, 0, &fcRGBA); |
712 |
switch (fcRGBA) { |
713 |
case FC_RGBA_NONE: |
714 |
ftRenderMode = FT_RENDER_MODE_NORMAL; |
715 |
break; |
716 |
case FC_RGBA_RGB: |
717 |
case FC_RGBA_BGR: |
718 |
ftRenderMode = FT_RENDER_MODE_LCD; |
719 |
horizontal = 1; |
720 |
break; |
721 |
case FC_RGBA_VRGB: |
722 |
case FC_RGBA_VBGR: |
723 |
ftRenderMode = FT_RENDER_MODE_LCD_V; |
724 |
horizontal = 0; |
725 |
break; |
726 |
default: |
727 |
ftRenderMode = FT_RENDER_MODE_NORMAL; |
728 |
break; |
729 |
} |
730 |
} |
731 |
|
732 |
// loading mode |
733 |
if (aaType == TEXT_AA_OFF) |
734 |
ftLoadFlags |= FT_LOAD_TARGET_MONO; |
735 |
else { |
736 |
int fcHintStyle = FC_HINT_NONE; |
737 |
if (pattern) |
738 |
FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &fcHintStyle); |
739 |
switch (fcHintStyle) { |
740 |
case FC_HINT_NONE: |
741 |
ftLoadFlags |= FT_LOAD_NO_HINTING; |
742 |
break; |
743 |
case FC_HINT_SLIGHT: |
744 |
ftLoadFlags |= FT_LOAD_TARGET_LIGHT; |
745 |
break; |
746 |
case FC_HINT_MEDIUM: |
747 |
ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
748 |
break; |
749 |
case FC_HINT_FULL: |
750 |
if (aaType == TEXT_AA_ON) |
751 |
ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
752 |
else |
753 |
ftLoadFlags |= horizontal ? FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_LCD_V; |
754 |
break; |
755 |
default: |
756 |
ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
757 |
break; |
758 |
} |
759 |
} |
760 |
|
761 |
// autohinting |
762 |
FcBool fcAutohint = 0; |
763 |
if (pattern && FcPatternGetBool(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch) |
764 |
if (fcAutohint) |
765 |
ftLoadFlags |= FT_LOAD_FORCE_AUTOHINT; |
766 |
|
767 |
// LCD filter |
768 |
int fcLCDFilter = FC_LCD_DEFAULT; |
769 |
if (pattern) |
770 |
FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &fcLCDFilter); |
771 |
switch (fcLCDFilter) { |
772 |
case FC_LCD_NONE: |
773 |
ftLcdFilter = FT_LCD_FILTER_NONE; |
774 |
break; |
775 |
case FC_LCD_DEFAULT: |
776 |
ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
777 |
break; |
778 |
case FC_LCD_LIGHT: |
779 |
ftLcdFilter = FT_LCD_FILTER_LIGHT; |
780 |
break; |
781 |
case FC_LCD_LEGACY: |
782 |
ftLcdFilter = FT_LCD_FILTER_LEGACY; |
783 |
break; |
784 |
default: |
785 |
ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
786 |
break; |
787 |
} |
788 |
|
789 |
if (pattern) |
790 |
FcPatternDestroy(pattern); |
791 |
|
792 |
rp->ftRenderMode = ftRenderMode; |
793 |
rp->ftLoadFlags = ftLoadFlags; |
794 |
rp->ftLcdFilter = ftLcdFilter; |
795 |
} |
796 |
|
669 |
/* |
797 |
/* |
670 |
* Class: sun_font_FreetypeFontScaler |
798 |
* Class: sun_font_FreetypeFontScaler |
671 |
* Method: getGlyphImageNative |
799 |
* Method: getGlyphImageNative |
Lines 698-728
Link Here
|
698 |
return ptr_to_jlong(getNullGlyphImage()); |
826 |
return ptr_to_jlong(getNullGlyphImage()); |
699 |
} |
827 |
} |
700 |
|
828 |
|
701 |
if (!context->useSbits) { |
829 |
RenderingProperties renderingProperties; |
702 |
renderFlags |= FT_LOAD_NO_BITMAP; |
830 |
readFontconfig((const FcChar8 *) scalerInfo->face->family_name, |
703 |
} |
831 |
context->ptsz, context->aaType, &renderingProperties); |
704 |
|
832 |
|
705 |
/* NB: in case of non identity transform |
|
|
706 |
we might also prefer to disable transform before hinting, |
707 |
and apply it explicitly after hinting is performed. |
708 |
Or we can disable hinting. */ |
709 |
|
710 |
/* select appropriate hinting mode */ |
711 |
if (context->aaType == TEXT_AA_OFF) { |
712 |
target = FT_LOAD_TARGET_MONO; |
713 |
} else if (context->aaType == TEXT_AA_ON) { |
714 |
target = FT_LOAD_TARGET_NORMAL; |
715 |
} else if (context->aaType == TEXT_AA_LCD_HRGB || |
716 |
context->aaType == TEXT_AA_LCD_HBGR) { |
717 |
target = FT_LOAD_TARGET_LCD; |
718 |
} else { |
719 |
target = FT_LOAD_TARGET_LCD_V; |
720 |
} |
721 |
renderFlags |= target; |
722 |
|
723 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
833 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
724 |
|
834 |
|
725 |
error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); |
835 |
FT_Library_SetLcdFilter(scalerInfo->library, renderingProperties.ftLcdFilter); |
|
|
836 |
error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags); |
837 |
|
726 |
if (error) { |
838 |
if (error) { |
727 |
//do not destroy scaler yet. |
839 |
//do not destroy scaler yet. |
728 |
//this can be problem of particular context (e.g. with bad transform) |
840 |
//this can be problem of particular context (e.g. with bad transform) |
Lines 741-749
Link Here
|
741 |
|
853 |
|
742 |
/* generate bitmap if it is not done yet |
854 |
/* generate bitmap if it is not done yet |
743 |
e.g. if algorithmic styling is performed and style was added to outline */ |
855 |
e.g. if algorithmic styling is performed and style was added to outline */ |
744 |
if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) { |
856 |
FT_Render_Glyph(ftglyph, renderingProperties.ftRenderMode); |
745 |
FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target)); |
|
|
746 |
} |
747 |
|
857 |
|
748 |
width = (UInt16) ftglyph->bitmap.width; |
858 |
width = (UInt16) ftglyph->bitmap.width; |
749 |
height = (UInt16) ftglyph->bitmap.rows; |
859 |
height = (UInt16) ftglyph->bitmap.rows; |
Lines 972-982
Link Here
|
972 |
return NULL; |
1082 |
return NULL; |
973 |
} |
1083 |
} |
974 |
|
1084 |
|
975 |
renderFlags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; |
1085 |
RenderingProperties renderingProperties; |
|
|
1086 |
readFontconfig((const FcChar8 *) scalerInfo->face->family_name, |
1087 |
context->ptsz, context->aaType, &renderingProperties); |
976 |
|
1088 |
|
977 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
1089 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
978 |
|
1090 |
|
979 |
error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); |
1091 |
error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags); |
|
|
1092 |
|
980 |
if (error) { |
1093 |
if (error) { |
981 |
return NULL; |
1094 |
return NULL; |
982 |
} |
1095 |
} |