Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: src/ports/SkFontHost_FreeType.cpp

Issue 23684041: improve bitmap font support (FreeType only) (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Correct selection logic, remove debug code. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkCanvas.h" 10 #include "SkCanvas.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #include <freetype/freetype.h> 51 #include <freetype/freetype.h>
52 #include <freetype/ftoutln.h> 52 #include <freetype/ftoutln.h>
53 #include <freetype/ftsizes.h> 53 #include <freetype/ftsizes.h>
54 #include <freetype/tttables.h> 54 #include <freetype/tttables.h>
55 #include <freetype/ftadvanc.h> 55 #include <freetype/ftadvanc.h>
56 #include <freetype/ftlcdfil.h> 56 #include <freetype/ftlcdfil.h>
57 #include <freetype/ftbitmap.h> 57 #include <freetype/ftbitmap.h>
58 #include <freetype/ftsynth.h> 58 #include <freetype/ftsynth.h>
59 #endif 59 #endif
60 60
61 // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA
62 // were introduced in FreeType 2.5.0.
63 // The following may be removed once FreeType 2.5.0 is required to build.
64 #ifndef FT_LOAD_COLOR
65 # define FT_LOAD_COLOR ( 1L << 20 )
66 # define FT_PIXEL_MODE_BGRA 7
67 #endif
68
69 // FT_HAS_COLOR and the corresponding FT_FACE_FLAG_COLOR
70 // were introduced in FreeType 2.5.1
71 // The following may be removed once FreeType 2.5.1 is required to build.
72 #ifndef FT_HAS_COLOR
73 # define FT_HAS_COLOR(face) false
74 #endif
75
61 //#define ENABLE_GLYPH_SPEW // for tracing calls 76 //#define ENABLE_GLYPH_SPEW // for tracing calls
62 //#define DUMP_STRIKE_CREATION 77 //#define DUMP_STRIKE_CREATION
63 78
64 //#define SK_GAMMA_APPLY_TO_A8 79 //#define SK_GAMMA_APPLY_TO_A8
65 80
66 using namespace skia_advanced_typeface_metrics_utils; 81 using namespace skia_advanced_typeface_metrics_utils;
67 82
68 static bool isLCD(const SkScalerContext::Rec& rec) { 83 static bool isLCD(const SkScalerContext::Rec& rec) {
69 switch (rec.fMaskFormat) { 84 switch (rec.fMaskFormat) {
70 case SkMask::kLCD16_Format: 85 case SkMask::kLCD16_Format:
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 192 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
178 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 193 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
179 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, 194 virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
180 SkPaint::FontMetrics* my) SK_OVERRIDE; 195 SkPaint::FontMetrics* my) SK_OVERRIDE;
181 virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE; 196 virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE;
182 197
183 private: 198 private:
184 SkFaceRec* fFaceRec; 199 SkFaceRec* fFaceRec;
185 FT_Face fFace; // reference to shared face in gFaceRecHead 200 FT_Face fFace; // reference to shared face in gFaceRecHead
186 FT_Size fFTSize; // our own copy 201 FT_Size fFTSize; // our own copy
202 FT_Int fStrikeIndex;
187 SkFixed fScaleX, fScaleY; 203 SkFixed fScaleX, fScaleY;
188 FT_Matrix fMatrix22; 204 FT_Matrix fMatrix22;
189 uint32_t fLoadGlyphFlags; 205 uint32_t fLoadGlyphFlags;
190 bool fDoLinearMetrics; 206 bool fDoLinearMetrics;
191 bool fLCDIsVert; 207 bool fLCDIsVert;
192 208
193 // Need scalar versions for generateFontMetrics 209 // Need scalar versions for generateFontMetrics
194 SkVector fScale; 210 SkVector fScale;
195 SkMatrix fMatrix22Scalar; 211 SkMatrix fMatrix22Scalar;
196 212
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], 760 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1],
745 FT_KERNING_UNSCALED, &delta); 761 FT_KERNING_UNSCALED, &delta);
746 if (err) { 762 if (err) {
747 return false; 763 return false;
748 } 764 }
749 adjustments[i] = delta.x; 765 adjustments[i] = delta.x;
750 } 766 }
751 return true; 767 return true;
752 } 768 }
753 769
770 static FT_Int chooseBitmapStrike(FT_Face face, SkFixed scaleY) {
771 // early out if face is bad
772 if (face == NULL) {
773 SkDEBUGF(("chooseBitmapStrike aborted due to NULL face\n"));
774 return -1;
775 }
776 // determine target ppem
777 FT_Pos targetPPEM = SkFixedToFDot6(scaleY);
778 // find a bitmap strike equal to or just larger than the requested size
779 FT_Int chosenStrikeIndex = -1;
780 FT_Pos chosenPPEM = 0;
781 for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIn dex) {
782 FT_Pos thisPPEM = face->available_sizes[strikeIndex].y_ppem;
783 if (thisPPEM == targetPPEM) {
784 // exact match - our search stops here
785 chosenPPEM = thisPPEM;
786 chosenStrikeIndex = strikeIndex;
787 break;
788 } else if (chosenPPEM < targetPPEM) {
789 // attempt to increase chosenPPEM
790 if (thisPPEM > chosenPPEM) {
791 chosenPPEM = thisPPEM;
792 chosenStrikeIndex = strikeIndex;
793 }
794 } else {
795 // attempt to decrease chosenPPEM, but not below targetPPEM
796 if (thisPPEM < chosenPPEM && thisPPEM > targetPPEM) {
797 chosenPPEM = thisPPEM;
798 chosenStrikeIndex = strikeIndex;
799 }
800 }
801 }
802 if (chosenStrikeIndex != -1) {
803 // use the chosen strike
804 FT_Error err = FT_Select_Size(face, chosenStrikeIndex);
805 if (err != 0) {
806 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_nam e,
807 chosenStrikeIndex, err));
808 chosenStrikeIndex = -1;
809 }
810 }
811 return chosenStrikeIndex;
812 }
813
754 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, 814 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
755 const SkDescriptor* desc) 815 const SkDescriptor* desc)
756 : SkScalerContext_FreeType_Base(typeface, desc) { 816 : SkScalerContext_FreeType_Base(typeface, desc) {
757 SkAutoMutexAcquire ac(gFTMutex); 817 SkAutoMutexAcquire ac(gFTMutex);
758 818
759 if (gFTCount == 0) { 819 if (gFTCount == 0) {
760 if (!InitFreetype()) { 820 if (!InitFreetype()) {
761 sk_throw(); 821 sk_throw();
762 } 822 }
763 } 823 }
764 ++gFTCount; 824 ++gFTCount;
765 825
766 // load the font file 826 // load the font file
827 fStrikeIndex = -1;
767 fFTSize = NULL; 828 fFTSize = NULL;
768 fFace = NULL; 829 fFace = NULL;
769 fFaceRec = ref_ft_face(typeface); 830 fFaceRec = ref_ft_face(typeface);
770 if (NULL == fFaceRec) { 831 if (NULL == fFaceRec) {
771 return; 832 return;
772 } 833 }
773 fFace = fFaceRec->fFace; 834 fFace = fFaceRec->fFace;
774 835
775 // compute our factors from the record 836 // compute our factors from the record
776 837
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 fMatrix22.xx = fMatrix22.yy = SK_Fixed1; 877 fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
817 fMatrix22.xy = fMatrix22.yx = 0; 878 fMatrix22.xy = fMatrix22.yx = 0;
818 } 879 }
819 fScale.set(sx, sy); 880 fScale.set(sx, sy);
820 fScaleX = SkScalarToFixed(sx); 881 fScaleX = SkScalarToFixed(sx);
821 fScaleY = SkScalarToFixed(sy); 882 fScaleY = SkScalarToFixed(sy);
822 883
823 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 884 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
824 885
825 // compute the flags we send to Load_Glyph 886 // compute the flags we send to Load_Glyph
887 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositi oning_Flag);
826 { 888 {
827 FT_Int32 loadFlags = FT_LOAD_DEFAULT; 889 FT_Int32 loadFlags = FT_LOAD_DEFAULT;
828 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPo sitioning_Flag);
829 890
830 if (SkMask::kBW_Format == fRec.fMaskFormat) { 891 if (SkMask::kBW_Format == fRec.fMaskFormat) {
831 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 892 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
832 loadFlags = FT_LOAD_TARGET_MONO; 893 loadFlags = FT_LOAD_TARGET_MONO;
833 if (fRec.getHinting() == SkPaint::kNo_Hinting) { 894 if (fRec.getHinting() == SkPaint::kNo_Hinting) {
834 loadFlags = FT_LOAD_NO_HINTING; 895 loadFlags = FT_LOAD_NO_HINTING;
835 linearMetrics = true; 896 linearMetrics = true;
836 } 897 }
837 } else { 898 } else {
838 switch (fRec.getHinting()) { 899 switch (fRec.getHinting()) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 937 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
877 // advances, as fontconfig and cairo do. 938 // advances, as fontconfig and cairo do.
878 // See http://code.google.com/p/skia/issues/detail?id=222. 939 // See http://code.google.com/p/skia/issues/detail?id=222.
879 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 940 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
880 941
881 // Use vertical layout if requested. 942 // Use vertical layout if requested.
882 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 943 if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
883 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; 944 loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
884 } 945 }
885 946
947 loadFlags |= FT_LOAD_COLOR;
948
886 fLoadGlyphFlags = loadFlags; 949 fLoadGlyphFlags = loadFlags;
887 fDoLinearMetrics = linearMetrics;
888 } 950 }
889 951
890 // now create the FT_Size 952 FT_Error err = FT_New_Size(fFace, &fFTSize);
953 if (err != 0) {
954 SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, fFace->family_na me));
955 fFace = NULL;
956 return;
957 }
958 err = FT_Activate_Size(fFTSize);
959 if (err != 0) {
960 SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", fFace, f ScaleX, fScaleY,
961 err));
962 fFTSize = NULL;
963 return;
964 }
891 965
892 { 966 if (FT_IS_SCALABLE(fFace)) {
893 FT_Error err; 967 err = FT_Set_Char_Size(fFace, SkFixedToFDot6(fScaleX), SkFixedToFDot6(fS caleY), 72, 72);
894
895 err = FT_New_Size(fFace, &fFTSize);
896 if (err != 0) { 968 if (err != 0) {
897 SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Si ze(0x%x, 0x%x) returned 0x%x\n", 969 SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n",
898 fFaceRec->fFontID, fScaleX, fScaleY, err)); 970 fFace, fScaleX, fScaleY, err));
899 fFace = NULL; 971 fFace = NULL;
900 return; 972 return;
901 } 973 }
974 FT_Set_Transform(fFace, &fMatrix22, NULL);
975 } else if (FT_HAS_FIXED_SIZES(fFace)) {
976 fStrikeIndex = chooseBitmapStrike(fFace, fScaleY);
977 if (fStrikeIndex == -1) {
978 SkDEBUGF(("no glyphs for font \"%s\" size %f?\n",
979 fFace->family_name, SkFixedToScalar(fScaleY))) ;
980 } else {
981 // FreeType does no provide linear metrics for bitmap fonts.
982 linearMetrics = false;
902 983
903 err = FT_Activate_Size(fFTSize); 984 // FreeType documentation says:
904 if (err != 0) { 985 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading.
905 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x ) returned 0x%x\n", 986 // Bitmap-only fonts ignore this flag.
906 fFaceRec->fFontID, fScaleX, fScaleY, err)); 987 //
907 fFTSize = NULL; 988 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag.
989 // Force this flag off for bitmap only fonts.
990 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP;
908 } 991 }
992 } else {
993 SkDEBUGF(("unknown kind of font \"%s\" size %f?\n",
994 fFace->family_name, SkFixedToScalar(fScaleY))) ;
995 }
909 996
910 err = FT_Set_Char_Size( fFace, 997 fDoLinearMetrics = linearMetrics;
911 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY) ,
912 72, 72);
913 if (err != 0) {
914 SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x ) returned 0x%x\n",
915 fFaceRec->fFontID, fScaleX, fScaleY, err));
916 fFace = NULL;
917 return;
918 }
919
920 FT_Set_Transform( fFace, &fMatrix22, NULL);
921 }
922 } 998 }
923 999
924 SkScalerContext_FreeType::~SkScalerContext_FreeType() { 1000 SkScalerContext_FreeType::~SkScalerContext_FreeType() {
925 SkAutoMutexAcquire ac(gFTMutex); 1001 SkAutoMutexAcquire ac(gFTMutex);
926 1002
927 if (fFTSize != NULL) { 1003 if (fFTSize != NULL) {
928 FT_Done_Size(fFTSize); 1004 FT_Done_Size(fFTSize);
929 } 1005 }
930 1006
931 if (fFace != NULL) { 1007 if (fFace != NULL) {
932 unref_ft_face(fFace); 1008 unref_ft_face(fFace);
933 } 1009 }
934 if (--gFTCount == 0) { 1010 if (--gFTCount == 0) {
935 // SkDEBUGF(("FT_Done_FreeType\n"));
936 FT_Done_FreeType(gFTLibrary); 1011 FT_Done_FreeType(gFTLibrary);
937 SkDEBUGCODE(gFTLibrary = NULL;) 1012 SkDEBUGCODE(gFTLibrary = NULL;)
938 } 1013 }
939 } 1014 }
940 1015
941 /* We call this before each use of the fFace, since we may be sharing 1016 /* We call this before each use of the fFace, since we may be sharing
942 this face with other context (at different sizes). 1017 this face with other context (at different sizes).
943 */ 1018 */
944 FT_Error SkScalerContext_FreeType::setupSize() { 1019 FT_Error SkScalerContext_FreeType::setupSize() {
945 FT_Error err = FT_Activate_Size(fFTSize); 1020 FT_Error err = FT_Activate_Size(fFTSize);
946
947 if (err != 0) { 1021 if (err != 0) {
948 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re turned 0x%x\n", 1022 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re turned 0x%x\n",
949 fFaceRec->fFontID, fScaleX, fScaleY, err)); 1023 fFaceRec->fFontID, fScaleX, fScaleY, err));
950 fFTSize = NULL; 1024 fFTSize = NULL;
951 } else { 1025 return err;
952 // seems we need to reset this every time (not sure why, but without it
953 // I get random italics from some other fFTSize)
954 FT_Set_Transform( fFace, &fMatrix22, NULL);
955 } 1026 }
956 return err; 1027
1028 // seems we need to reset this every time (not sure why, but without it
1029 // I get random italics from some other fFTSize)
1030 FT_Set_Transform(fFace, &fMatrix22, NULL);
1031 return 0;
957 } 1032 }
958 1033
959 unsigned SkScalerContext_FreeType::generateGlyphCount() { 1034 unsigned SkScalerContext_FreeType::generateGlyphCount() {
960 return fFace->num_glyphs; 1035 return fFace->num_glyphs;
961 } 1036 }
962 1037
963 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 1038 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) {
964 return SkToU16(FT_Get_Char_Index( fFace, uni )); 1039 return SkToU16(FT_Get_Char_Index( fFace, uni ));
965 } 1040 }
966 1041
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 if (fLCDIsVert) { 1131 if (fLCDIsVert) {
1057 glyph->fHeight += gLCDExtra; 1132 glyph->fHeight += gLCDExtra;
1058 glyph->fTop -= gLCDExtra >> 1; 1133 glyph->fTop -= gLCDExtra >> 1;
1059 } else { 1134 } else {
1060 glyph->fWidth += gLCDExtra; 1135 glyph->fWidth += gLCDExtra;
1061 glyph->fLeft -= gLCDExtra >> 1; 1136 glyph->fLeft -= gLCDExtra >> 1;
1062 } 1137 }
1063 } 1138 }
1064 } 1139 }
1065 1140
1141 inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) {
1142 glyph.fWidth *= scale;
1143 glyph.fHeight *= scale;
1144 glyph.fTop *= scale;
1145 glyph.fLeft *= scale;
1146
1147 SkFixed fixedScale = SkScalarToFixed(scale);
1148 glyph.fAdvanceX = SkFixedMul(glyph.fAdvanceX, fixedScale);
1149 glyph.fAdvanceY = SkFixedMul(glyph.fAdvanceY, fixedScale);
1150 }
1151
1066 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 1152 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
1067 SkAutoMutexAcquire ac(gFTMutex); 1153 SkAutoMutexAcquire ac(gFTMutex);
1068 1154
1069 glyph->fRsbDelta = 0; 1155 glyph->fRsbDelta = 0;
1070 glyph->fLsbDelta = 0; 1156 glyph->fLsbDelta = 0;
1071 1157
1072 FT_Error err; 1158 FT_Error err;
1073 1159
1074 if (this->setupSize()) { 1160 if (this->setupSize()) {
1075 goto ERROR; 1161 goto ERROR;
1076 } 1162 }
1077 1163
1078 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl ags ); 1164 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl ags );
1079 if (err != 0) { 1165 if (err != 0) {
1080 #if 0 1166 #if 0
1081 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph( glyph:%d flags:%x) returned 0x%x\n", 1167 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph( glyph:%d flags:%x) returned 0x%x\n",
1082 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad GlyphFlags, err)); 1168 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad GlyphFlags, err));
1083 #endif 1169 #endif
1084 ERROR: 1170 ERROR:
1085 glyph->zeroMetrics(); 1171 glyph->zeroMetrics();
1086 return; 1172 return;
1087 } 1173 }
1088 1174
1089 switch ( fFace->glyph->format ) { 1175 switch ( fFace->glyph->format ) {
1090 case FT_GLYPH_FORMAT_OUTLINE: { 1176 case FT_GLYPH_FORMAT_OUTLINE:
1091 FT_BBox bbox;
1092
1093 if (0 == fFace->glyph->outline.n_contours) { 1177 if (0 == fFace->glyph->outline.n_contours) {
1094 glyph->fWidth = 0; 1178 glyph->fWidth = 0;
1095 glyph->fHeight = 0; 1179 glyph->fHeight = 0;
1096 glyph->fTop = 0; 1180 glyph->fTop = 0;
1097 glyph->fLeft = 0; 1181 glyph->fLeft = 0;
1098 break; 1182 } else {
1183 if (fRec.fFlags & kEmbolden_Flag && !(fFace->style_flags & FT_STYLE_ FLAG_BOLD)) {
1184 emboldenOutline(fFace, &fFace->glyph->outline);
1185 }
1186
1187 FT_BBox bbox;
1188 getBBoxForCurrentGlyph(glyph, &bbox, true);
1189
1190 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin));
1191 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin));
1192 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax));
1193 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin));
1194
1195 updateGlyphIfLCD(glyph);
1099 } 1196 }
1100
1101 if (fRec.fFlags & kEmbolden_Flag) {
1102 emboldenOutline(fFace, &fFace->glyph->outline);
1103 }
1104
1105 getBBoxForCurrentGlyph(glyph, &bbox, true);
1106
1107 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin));
1108 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin));
1109 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax));
1110 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin));
1111
1112 updateGlyphIfLCD(glyph);
1113
1114 break; 1197 break;
1115 }
1116 1198
1117 case FT_GLYPH_FORMAT_BITMAP: 1199 case FT_GLYPH_FORMAT_BITMAP:
1118 if (fRec.fFlags & kEmbolden_Flag) { 1200 if (fRec.fFlags & kEmbolden_Flag) {
1119 FT_GlyphSlot_Own_Bitmap(fFace->glyph); 1201 FT_GlyphSlot_Own_Bitmap(fFace->glyph);
1120 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmbolde nStrength, 0); 1202 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmbolde nStrength, 0);
1121 } 1203 }
1122 1204
1123 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1205 if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
1124 FT_Vector vector; 1206 FT_Vector vector;
1125 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric s.horiBearingX; 1207 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric s.horiBearingX;
1126 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri cs.horiBearingY; 1208 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri cs.horiBearingY;
1127 FT_Vector_Transform(&vector, &fMatrix22); 1209 FT_Vector_Transform(&vector, &fMatrix22);
1128 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); 1210 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
1129 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); 1211 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y);
1130 } 1212 }
1131 1213
1214 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
1215 glyph->fMaskFormat = SkMask::kARGB32_Format;
1216 }
1217
1132 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); 1218 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width);
1133 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); 1219 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows);
1134 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); 1220 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top);
1135 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); 1221 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left);
1136 break; 1222 break;
1137 1223
1138 default: 1224 default:
1139 SkDEBUGFAIL("unknown glyph format"); 1225 SkDEBUGFAIL("unknown glyph format");
1140 goto ERROR; 1226 goto ERROR;
1141 } 1227 }
(...skipping 14 matching lines...) Expand all
1156 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); 1242 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
1157 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); 1243 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
1158 1244
1159 if (fRec.fFlags & kDevKernText_Flag) { 1245 if (fRec.fFlags & kDevKernText_Flag) {
1160 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 1246 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
1161 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1247 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
1162 } 1248 }
1163 } 1249 }
1164 } 1250 }
1165 1251
1252 if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP && fScaleY && fFace->size ->metrics.y_ppem) {
1253 // NOTE: both dimensions are scaled by y_ppem. this is WAI.
1254 scaleGlyphMetrics(*glyph, SkScalarDiv(SkFixedToScalar(fScaleY),
1255 SkIntToScalar(fFace->size->metrics .y_ppem)));
1256 }
1166 1257
1167 #ifdef ENABLE_GLYPH_SPEW 1258 #ifdef ENABLE_GLYPH_SPEW
1168 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); 1259 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY));
1169 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyp hCount), fLoadGlyphFlags, glyph->fWidth)); 1260 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyp hCount), fLoadGlyphFlags, glyph->fWidth));
1170 #endif 1261 #endif
1171 } 1262 }
1172 1263
1173 1264
1174 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 1265 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
1175 SkAutoMutexAcquire ac(gFTMutex); 1266 SkAutoMutexAcquire ac(gFTMutex);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1243 if (mx) { 1334 if (mx) {
1244 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); 1335 sk_bzero(mx, sizeof(SkPaint::FontMetrics));
1245 } 1336 }
1246 if (my) { 1337 if (my) {
1247 sk_bzero(my, sizeof(SkPaint::FontMetrics)); 1338 sk_bzero(my, sizeof(SkPaint::FontMetrics));
1248 } 1339 }
1249 return; 1340 return;
1250 } 1341 }
1251 1342
1252 FT_Face face = fFace; 1343 FT_Face face = fFace;
1253 int upem = face->units_per_EM; 1344 SkScalar scaleX = fScale.x();
1254 if (upem <= 0) { 1345 SkScalar scaleY = fScale.y();
1346 SkScalar mxy = fMatrix22Scalar.getSkewX() * scaleY;
1347 SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY;
1348
1349 // fetch units/EM from "head" table if needed (ie for bitmap fonts)
1350 SkScalar upem = SkIntToScalar(face->units_per_EM);
1351 if (!upem) {
1352 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head);
1353 if (ttHeader) {
1354 upem = SkIntToScalar(ttHeader->Units_Per_EM);
1355 }
1356 }
1357
1358 // use the os/2 table as a source of reasonable defaults.
1359 SkScalar x_height = 0.0f;
1360 SkScalar avgCharWidth = 0.0f;
1361 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1362 if (os2) {
1363 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem;
1364 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem;
1365 }
1366
1367 // pull from format-specific metrics as needed
1368 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax;
1369 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font
1370 ascent = -SkIntToScalar(face->ascender) / upem;
1371 descent = -SkIntToScalar(face->descender) / upem;
1372 leading = SkIntToScalar(face->height + (face->descender - face->ascender )) / upem;
1373 xmin = SkIntToScalar(face->bbox.xMin) / upem;
1374 xmax = SkIntToScalar(face->bbox.xMax) / upem;
1375 ymin = -SkIntToScalar(face->bbox.yMin) / upem;
1376 ymax = -SkIntToScalar(face->bbox.yMax) / upem;
1377 // we may be able to synthesize x_height from outline
1378 if (!x_height) {
1379 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x');
1380 if (x_glyph) {
1381 FT_BBox bbox;
1382 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags);
1383 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_ STYLE_FLAG_BOLD)) {
1384 emboldenOutline(fFace, &fFace->glyph->outline);
1385 }
1386 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
1387 x_height = SkIntToScalar(bbox.yMax) / 64.0f;
1388 }
1389 }
1390 } else if (fStrikeIndex != -1) { // bitmap strike metrics
1391 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem);
1392 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem);
1393 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f);
1394 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f );
1395 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f))
1396 + ascent - descent;
1397 xmin = 0.0f;
1398 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem;
1399 ymin = descent + leading;
1400 ymax = ascent - descent;
1401 if (!x_height) {
1402 x_height = -ascent;
1403 }
1404 if (!avgCharWidth) {
1405 avgCharWidth = xmax - xmin;
1406 }
1407 } else {
1255 goto ERROR; 1408 goto ERROR;
1256 } 1409 }
1257 1410
1258 SkPoint pts[6]; 1411 // synthesize elements that were not provided by the os/2 table or format-sp ecific metrics
1259 SkFixed ys[6]; 1412 if (!x_height) {
1260 SkScalar scaleY = fScale.y(); 1413 x_height = -ascent;
1261 SkScalar mxy = fMatrix22Scalar.getSkewX(); 1414 }
1262 SkScalar myy = fMatrix22Scalar.getScaleY(); 1415 if (!avgCharWidth) {
1263 SkScalar xmin = SkIntToScalar(face->bbox.xMin) / upem; 1416 avgCharWidth = xmax - xmin;
1264 SkScalar xmax = SkIntToScalar(face->bbox.xMax) / upem;
1265
1266 int leading = face->height - (face->ascender + -face->descender);
1267 if (leading < 0) {
1268 leading = 0;
1269 } 1417 }
1270 1418
1271 // Try to get the OS/2 table from the font. This contains the specific 1419 // disallow negative linespacing
1272 // average font width metrics which Windows uses. 1420 if (leading < 0.0f) {
1273 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1421 leading = 0.0f;
1274
1275 ys[0] = -face->bbox.yMax;
1276 ys[1] = -face->ascender;
1277 ys[2] = -face->descender;
1278 ys[3] = -face->bbox.yMin;
1279 ys[4] = leading;
1280 ys[5] = os2 ? os2->xAvgCharWidth : 0;
1281
1282 SkScalar x_height;
1283 if (os2 && os2->sxHeight) {
1284 x_height = fScale.x() * os2->sxHeight / upem;
1285 } else {
1286 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x');
1287 if (x_glyph) {
1288 FT_BBox bbox;
1289 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags);
1290 if (fRec.fFlags & kEmbolden_Flag) {
1291 emboldenOutline(fFace, &fFace->glyph->outline);
1292 }
1293 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
1294 x_height = bbox.yMax / 64.0f;
1295 } else {
1296 x_height = 0;
1297 }
1298 }
1299
1300 // convert upem-y values into scalar points
1301 for (int i = 0; i < 6; i++) {
1302 SkScalar y = scaleY * ys[i] / upem;
1303 pts[i].set(y * mxy, y * myy);
1304 } 1422 }
1305 1423
1306 if (mx) { 1424 if (mx) {
1307 mx->fTop = pts[0].fX; 1425 mx->fTop = ymax * mxy;
1308 mx->fAscent = pts[1].fX; 1426 mx->fAscent = ascent * mxy;
1309 mx->fDescent = pts[2].fX; 1427 mx->fDescent = descent * mxy;
1310 mx->fBottom = pts[3].fX; 1428 mx->fBottom = ymin * mxy;
1311 mx->fLeading = pts[4].fX; 1429 mx->fLeading = leading * mxy;
1312 mx->fAvgCharWidth = pts[5].fX; 1430 mx->fAvgCharWidth = avgCharWidth * mxy;
1313 mx->fXMin = xmin; 1431 mx->fXMin = xmin;
1314 mx->fXMax = xmax; 1432 mx->fXMax = xmax;
1315 mx->fXHeight = x_height; 1433 mx->fXHeight = x_height;
1316 } 1434 }
1317 if (my) { 1435 if (my) {
1318 my->fTop = pts[0].fY; 1436 my->fTop = ymax * myy;
1319 my->fAscent = pts[1].fY; 1437 my->fAscent = ascent * myy;
1320 my->fDescent = pts[2].fY; 1438 my->fDescent = descent * myy;
1321 my->fBottom = pts[3].fY; 1439 my->fBottom = ymin * myy;
1322 my->fLeading = pts[4].fY; 1440 my->fLeading = leading * myy;
1323 my->fAvgCharWidth = pts[5].fY; 1441 my->fAvgCharWidth = avgCharWidth * myy;
1324 my->fXMin = xmin; 1442 my->fXMin = xmin;
1325 my->fXMax = xmax; 1443 my->fXMax = xmax;
1326 my->fXHeight = x_height; 1444 my->fXHeight = x_height;
1327 } 1445 }
1328 } 1446 }
1329 1447
1330 /////////////////////////////////////////////////////////////////////////////// 1448 ///////////////////////////////////////////////////////////////////////////////
1331 1449
1332 #include "SkUtils.h" 1450 #include "SkUtils.h"
1333 1451
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 *style = (SkTypeface::Style) tempStyle; 1641 *style = (SkTypeface::Style) tempStyle;
1524 } 1642 }
1525 if (isFixedPitch) { 1643 if (isFixedPitch) {
1526 *isFixedPitch = FT_IS_FIXED_WIDTH(face); 1644 *isFixedPitch = FT_IS_FIXED_WIDTH(face);
1527 } 1645 }
1528 1646
1529 FT_Done_Face(face); 1647 FT_Done_Face(face);
1530 FT_Done_FreeType(library); 1648 FT_Done_FreeType(library);
1531 return true; 1649 return true;
1532 } 1650 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698