OLD | NEW |
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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 private: | 183 private: |
184 SkFaceRec* fFaceRec; | 184 SkFaceRec* fFaceRec; |
185 FT_Face fFace; // reference to shared face in gFaceRecHead | 185 FT_Face fFace; // reference to shared face in gFaceRecHead |
186 FT_Size fFTSize; // our own copy | 186 FT_Size fFTSize; // our own copy |
187 SkFixed fScaleX, fScaleY; | 187 SkFixed fScaleX, fScaleY; |
188 FT_Matrix fMatrix22; | 188 FT_Matrix fMatrix22; |
189 uint32_t fLoadGlyphFlags; | 189 uint32_t fLoadGlyphFlags; |
190 bool fDoLinearMetrics; | 190 bool fDoLinearMetrics; |
191 bool fLCDIsVert; | 191 bool fLCDIsVert; |
192 | 192 |
| 193 // since different scalercontext may share the same face |
| 194 // using a ID to identify which settings are activated |
| 195 // this can help us to skip some unnecessary FreeType2 calls |
| 196 uint32_t fUniqueID; |
| 197 |
193 // Need scalar versions for generateFontMetrics | 198 // Need scalar versions for generateFontMetrics |
194 SkVector fScale; | 199 SkVector fScale; |
195 SkMatrix fMatrix22Scalar; | 200 SkMatrix fMatrix22Scalar; |
196 | 201 |
197 FT_Error setupSize(); | 202 FT_Error setupSize(); |
198 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, | 203 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, |
199 bool snapToPixelBoundary = false); | 204 bool snapToPixelBoundary = false); |
200 // Caller must lock gFTMutex before calling this function. | 205 // Caller must lock gFTMutex before calling this function. |
201 void updateGlyphIfLCD(SkGlyph* glyph); | 206 void updateGlyphIfLCD(SkGlyph* glyph); |
202 }; | 207 }; |
203 | 208 |
204 /////////////////////////////////////////////////////////////////////////// | 209 /////////////////////////////////////////////////////////////////////////// |
205 /////////////////////////////////////////////////////////////////////////// | 210 /////////////////////////////////////////////////////////////////////////// |
206 | 211 |
207 struct SkFaceRec { | 212 struct SkFaceRec { |
208 SkFaceRec* fNext; | 213 SkFaceRec* fNext; |
209 FT_Face fFace; | 214 FT_Face fFace; |
210 FT_StreamRec fFTStream; | 215 FT_StreamRec fFTStream; |
211 SkStream* fSkStream; | 216 SkStream* fSkStream; |
212 uint32_t fRefCnt; | 217 uint32_t fRefCnt; |
213 uint32_t fFontID; | 218 uint32_t fFontID; |
214 | 219 |
| 220 // record some information about the last glyph loaded |
| 221 // drawText will generateImage just after generateMetrics in most cases |
| 222 // a simple check can help us to skip the unnecessary call to FT_Load_Glyph |
| 223 // which is time consuming, especially for composite glyphs |
| 224 uint32_t fActivatedContextID; |
| 225 // glyph that has been already loaded, which is also ready for generateImage |
| 226 uint16_t fGlyphLoaded; |
| 227 |
215 // assumes ownership of the stream, will call unref() when its done | 228 // assumes ownership of the stream, will call unref() when its done |
216 SkFaceRec(SkStream* strm, uint32_t fontID); | 229 SkFaceRec(SkStream* strm, uint32_t fontID); |
217 ~SkFaceRec() { | 230 ~SkFaceRec() { |
218 fSkStream->unref(); | 231 fSkStream->unref(); |
219 } | 232 } |
220 }; | 233 }; |
221 | 234 |
222 extern "C" { | 235 extern "C" { |
223 static unsigned long sk_stream_read(FT_Stream stream, | 236 static unsigned long sk_stream_read(FT_Stream stream, |
224 unsigned long offset, | 237 unsigned long offset, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { | 355 AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { |
343 gFTMutex.acquire(); | 356 gFTMutex.acquire(); |
344 if (1 == ++gFTCount) { | 357 if (1 == ++gFTCount) { |
345 if (!InitFreetype()) { | 358 if (!InitFreetype()) { |
346 sk_throw(); | 359 sk_throw(); |
347 } | 360 } |
348 } | 361 } |
349 fRec = ref_ft_face(tf); | 362 fRec = ref_ft_face(tf); |
350 if (fRec) { | 363 if (fRec) { |
351 fFace = fRec->fFace; | 364 fFace = fRec->fFace; |
| 365 // someone will access to the FreeType face |
| 366 fRec->fActivatedContextID = 0; |
| 367 fRec->fGlyphLoaded = 0; |
352 } | 368 } |
353 } | 369 } |
354 | 370 |
355 ~AutoFTAccess() { | 371 ~AutoFTAccess() { |
356 if (fFace) { | 372 if (fFace) { |
357 unref_ft_face(fFace); | 373 unref_ft_face(fFace); |
358 } | 374 } |
359 if (0 == --gFTCount) { | 375 if (0 == --gFTCount) { |
360 FT_Done_FreeType(gFTLibrary); | 376 FT_Done_FreeType(gFTLibrary); |
361 } | 377 } |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 | 781 |
766 // load the font file | 782 // load the font file |
767 fFTSize = NULL; | 783 fFTSize = NULL; |
768 fFace = NULL; | 784 fFace = NULL; |
769 fFaceRec = ref_ft_face(typeface); | 785 fFaceRec = ref_ft_face(typeface); |
770 if (NULL == fFaceRec) { | 786 if (NULL == fFaceRec) { |
771 return; | 787 return; |
772 } | 788 } |
773 fFace = fFaceRec->fFace; | 789 fFace = fFaceRec->fFace; |
774 | 790 |
| 791 // set ID for current scaler context |
| 792 // start from 1, regarding 0 as invalid |
| 793 static uint32_t gScalerContextID = 1; |
| 794 fUniqueID = gScalerContextID++; |
| 795 |
775 // compute our factors from the record | 796 // compute our factors from the record |
776 | 797 |
777 SkMatrix m; | 798 SkMatrix m; |
778 | 799 |
779 fRec.getSingleMatrix(&m); | 800 fRec.getSingleMatrix(&m); |
780 | 801 |
781 #ifdef DUMP_STRIKE_CREATION | 802 #ifdef DUMP_STRIKE_CREATION |
782 SkString keyString; | 803 SkString keyString; |
783 SkFontHost::GetDescriptorKeyString(desc, &keyString); | 804 SkFontHost::GetDescriptorKeyString(desc, &keyString); |
784 printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n",
SkScalarToFloat(fRec.fTextSize), | 805 printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n",
SkScalarToFloat(fRec.fTextSize), |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 | 906 |
886 fLoadGlyphFlags = loadFlags; | 907 fLoadGlyphFlags = loadFlags; |
887 fDoLinearMetrics = linearMetrics; | 908 fDoLinearMetrics = linearMetrics; |
888 } | 909 } |
889 | 910 |
890 // now create the FT_Size | 911 // now create the FT_Size |
891 | 912 |
892 { | 913 { |
893 FT_Error err; | 914 FT_Error err; |
894 | 915 |
| 916 // no activated scaler context setting for the face |
| 917 fFaceRec->fActivatedContextID = 0; |
| 918 // regarding glyph 0 as an invalid glyph outline that we need to reload |
| 919 fFaceRec->fGlyphLoaded = 0; |
| 920 |
895 err = FT_New_Size(fFace, &fFTSize); | 921 err = FT_New_Size(fFace, &fFTSize); |
896 if (err != 0) { | 922 if (err != 0) { |
897 SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Si
ze(0x%x, 0x%x) returned 0x%x\n", | 923 SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Si
ze(0x%x, 0x%x) returned 0x%x\n", |
898 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 924 fFaceRec->fFontID, fScaleX, fScaleY, err)); |
899 fFace = NULL; | 925 fFace = NULL; |
900 return; | 926 return; |
901 } | 927 } |
902 | 928 |
903 err = FT_Activate_Size(fFTSize); | 929 err = FT_Activate_Size(fFTSize); |
904 if (err != 0) { | 930 if (err != 0) { |
905 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x
) returned 0x%x\n", | 931 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x
) returned 0x%x\n", |
906 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 932 fFaceRec->fFontID, fScaleX, fScaleY, err)); |
907 fFTSize = NULL; | 933 fFTSize = NULL; |
908 } | 934 } |
909 | 935 |
910 err = FT_Set_Char_Size( fFace, | 936 err = FT_Set_Char_Size( fFace, |
911 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY)
, | 937 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY)
, |
912 72, 72); | 938 72, 72); |
913 if (err != 0) { | 939 if (err != 0) { |
914 SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x
) returned 0x%x\n", | 940 SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x
) returned 0x%x\n", |
915 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 941 fFaceRec->fFontID, fScaleX, fScaleY, err)); |
916 fFace = NULL; | 942 fFace = NULL; |
917 return; | 943 return; |
918 } | 944 } |
919 | 945 |
920 FT_Set_Transform( fFace, &fMatrix22, NULL); | 946 FT_Set_Transform( fFace, &fMatrix22, NULL); |
| 947 |
| 948 // current scaler context setting is enabled for the face |
| 949 fFaceRec->fActivatedContextID = fUniqueID; |
921 } | 950 } |
922 } | 951 } |
923 | 952 |
924 SkScalerContext_FreeType::~SkScalerContext_FreeType() { | 953 SkScalerContext_FreeType::~SkScalerContext_FreeType() { |
925 SkAutoMutexAcquire ac(gFTMutex); | 954 SkAutoMutexAcquire ac(gFTMutex); |
926 | 955 |
927 if (fFTSize != NULL) { | 956 if (fFTSize != NULL) { |
928 FT_Done_Size(fFTSize); | 957 FT_Done_Size(fFTSize); |
929 } | 958 } |
930 | 959 |
931 if (fFace != NULL) { | 960 if (fFace != NULL) { |
932 unref_ft_face(fFace); | 961 unref_ft_face(fFace); |
933 } | 962 } |
934 if (--gFTCount == 0) { | 963 if (--gFTCount == 0) { |
935 // SkDEBUGF(("FT_Done_FreeType\n")); | 964 // SkDEBUGF(("FT_Done_FreeType\n")); |
936 FT_Done_FreeType(gFTLibrary); | 965 FT_Done_FreeType(gFTLibrary); |
937 SkDEBUGCODE(gFTLibrary = NULL;) | 966 SkDEBUGCODE(gFTLibrary = NULL;) |
938 } | 967 } |
939 } | 968 } |
940 | 969 |
941 /* We call this before each use of the fFace, since we may be sharing | 970 /* We call this before each use of the fFace, since we may be sharing |
942 this face with other context (at different sizes). | 971 this face with other context (at different sizes). |
943 */ | 972 */ |
944 FT_Error SkScalerContext_FreeType::setupSize() { | 973 FT_Error SkScalerContext_FreeType::setupSize() { |
945 FT_Error err = FT_Activate_Size(fFTSize); | 974 FT_Error err = 0; |
946 | 975 |
947 if (err != 0) { | 976 if (fFaceRec->fActivatedContextID != fUniqueID) { |
948 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re
turned 0x%x\n", | 977 // no scalercontext settings are activated for the FreeType face now |
949 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 978 fFaceRec->fActivatedContextID = 0; |
950 fFTSize = NULL; | 979 fFaceRec->fGlyphLoaded = 0; |
951 } else { | 980 err = FT_Activate_Size(fFTSize); |
952 // seems we need to reset this every time (not sure why, but without it | 981 if (err != 0) { |
953 // I get random italics from some other fFTSize) | 982 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x
) returned 0x%x\n", |
954 FT_Set_Transform( fFace, &fMatrix22, NULL); | 983 fFaceRec->fFontID, fScaleX, fScaleY, err)); |
| 984 fFTSize = NULL; |
| 985 } else { |
| 986 // seems we need to reset this every time (not sure why, but without
it |
| 987 // I get random italics from some other fFTSize) |
| 988 FT_Set_Transform( fFace, &fMatrix22, NULL); |
| 989 // current scalercontext settings are activated |
| 990 fFaceRec->fActivatedContextID = fUniqueID; |
| 991 } |
955 } | 992 } |
956 return err; | 993 return err; |
957 } | 994 } |
958 | 995 |
959 unsigned SkScalerContext_FreeType::generateGlyphCount() { | 996 unsigned SkScalerContext_FreeType::generateGlyphCount() { |
960 return fFace->num_glyphs; | 997 return fFace->num_glyphs; |
961 } | 998 } |
962 | 999 |
963 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { | 1000 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { |
964 return SkToU16(FT_Get_Char_Index( fFace, uni )); | 1001 return SkToU16(FT_Get_Char_Index( fFace, uni )); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 | 1105 |
1069 glyph->fRsbDelta = 0; | 1106 glyph->fRsbDelta = 0; |
1070 glyph->fLsbDelta = 0; | 1107 glyph->fLsbDelta = 0; |
1071 | 1108 |
1072 FT_Error err; | 1109 FT_Error err; |
1073 | 1110 |
1074 if (this->setupSize()) { | 1111 if (this->setupSize()) { |
1075 goto ERROR; | 1112 goto ERROR; |
1076 } | 1113 } |
1077 | 1114 |
1078 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl
ags ); | 1115 // this glyph will be loaded to FreeType glyph slot |
| 1116 fFaceRec->fGlyphLoaded = glyph->getGlyphID(fBaseGlyphCount); |
| 1117 err = FT_Load_Glyph( fFace, fFaceRec->fGlyphLoaded, fLoadGlyphFlags ); |
1079 if (err != 0) { | 1118 if (err != 0) { |
1080 #if 0 | 1119 #if 0 |
1081 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(
glyph:%d flags:%x) returned 0x%x\n", | 1120 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)); | 1121 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad
GlyphFlags, err)); |
1083 #endif | 1122 #endif |
1084 ERROR: | 1123 ERROR: |
1085 glyph->zeroMetrics(); | 1124 glyph->zeroMetrics(); |
| 1125 // glyph not loadded |
| 1126 fFaceRec->fGlyphLoaded = 0; |
1086 return; | 1127 return; |
1087 } | 1128 } |
| 1129 emboldenIfNeeded(fFace, fFace->glyph); |
1088 | 1130 |
1089 switch ( fFace->glyph->format ) { | 1131 switch ( fFace->glyph->format ) { |
1090 case FT_GLYPH_FORMAT_OUTLINE: { | 1132 case FT_GLYPH_FORMAT_OUTLINE: { |
1091 FT_BBox bbox; | 1133 FT_BBox bbox; |
1092 | 1134 |
1093 if (0 == fFace->glyph->outline.n_contours) { | 1135 if (0 == fFace->glyph->outline.n_contours) { |
1094 glyph->fWidth = 0; | 1136 glyph->fWidth = 0; |
1095 glyph->fHeight = 0; | 1137 glyph->fHeight = 0; |
1096 glyph->fTop = 0; | 1138 glyph->fTop = 0; |
1097 glyph->fLeft = 0; | 1139 glyph->fLeft = 0; |
1098 break; | 1140 break; |
1099 } | 1141 } |
1100 | 1142 |
1101 if (fRec.fFlags & kEmbolden_Flag) { | |
1102 emboldenOutline(fFace, &fFace->glyph->outline); | |
1103 } | |
1104 | |
1105 getBBoxForCurrentGlyph(glyph, &bbox, true); | 1143 getBBoxForCurrentGlyph(glyph, &bbox, true); |
1106 | 1144 |
1107 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); | 1145 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); |
1108 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); | 1146 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); |
1109 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); | 1147 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); |
1110 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); | 1148 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); |
1111 | 1149 |
1112 updateGlyphIfLCD(glyph); | 1150 updateGlyphIfLCD(glyph); |
1113 | 1151 |
1114 break; | 1152 break; |
1115 } | 1153 } |
1116 | 1154 |
1117 case FT_GLYPH_FORMAT_BITMAP: | 1155 case FT_GLYPH_FORMAT_BITMAP: |
1118 if (fRec.fFlags & kEmbolden_Flag) { | |
1119 FT_GlyphSlot_Own_Bitmap(fFace->glyph); | |
1120 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmbolde
nStrength, 0); | |
1121 } | |
1122 | |
1123 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1156 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1124 FT_Vector vector; | 1157 FT_Vector vector; |
1125 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric
s.horiBearingX; | 1158 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric
s.horiBearingX; |
1126 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri
cs.horiBearingY; | 1159 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri
cs.horiBearingY; |
1127 FT_Vector_Transform(&vector, &fMatrix22); | 1160 FT_Vector_Transform(&vector, &fMatrix22); |
1128 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); | 1161 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); |
1129 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); | 1162 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); |
1130 } | 1163 } |
1131 | 1164 |
1132 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); | 1165 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); | 1201 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)); | 1202 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyp
hCount), fLoadGlyphFlags, glyph->fWidth)); |
1170 #endif | 1203 #endif |
1171 } | 1204 } |
1172 | 1205 |
1173 | 1206 |
1174 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { | 1207 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { |
1175 SkAutoMutexAcquire ac(gFTMutex); | 1208 SkAutoMutexAcquire ac(gFTMutex); |
1176 | 1209 |
1177 FT_Error err; | 1210 FT_Error err; |
| 1211 uint16_t glyphLoaded; |
1178 | 1212 |
1179 if (this->setupSize()) { | 1213 if (this->setupSize()) { |
1180 goto ERROR; | 1214 goto ERROR; |
1181 } | 1215 } |
1182 | 1216 |
1183 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFla
gs); | 1217 glyphLoaded = fFaceRec->fGlyphLoaded; |
1184 if (err != 0) { | 1218 // no need to remember what is in the FreeType glyph slot |
1185 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:
%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", | 1219 // since the skia glyph cache won't query image for the same glyph shortly |
1186 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeig
ht, glyph.rowBytes(), fLoadGlyphFlags, err)); | 1220 fFaceRec->fGlyphLoaded = 0; |
1187 ERROR: | 1221 if (glyphLoaded == 0 || glyphLoaded != glyph.getGlyphID(fBaseGlyphCount)) { |
1188 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); | 1222 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyp
hFlags); |
1189 return; | 1223 if (err != 0) { |
| 1224 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(gl
yph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", |
| 1225 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.f
Height, glyph.rowBytes(), fLoadGlyphFlags, err)); |
| 1226 ERROR: |
| 1227 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); |
| 1228 return; |
| 1229 } |
| 1230 emboldenIfNeeded(fFace, fFace->glyph); |
1190 } | 1231 } |
1191 | 1232 |
1192 generateGlyphImage(fFace, glyph); | 1233 generateGlyphImage(fFace, glyph); |
1193 } | 1234 } |
1194 | 1235 |
1195 | 1236 |
1196 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, | 1237 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, |
1197 SkPath* path) { | 1238 SkPath* path) { |
1198 SkAutoMutexAcquire ac(gFTMutex); | 1239 SkAutoMutexAcquire ac(gFTMutex); |
1199 | 1240 |
1200 SkASSERT(&glyph && path); | 1241 SkASSERT(&glyph && path); |
1201 | 1242 |
1202 if (this->setupSize()) { | 1243 if (this->setupSize()) { |
1203 path->reset(); | 1244 path->reset(); |
1204 return; | 1245 return; |
1205 } | 1246 } |
1206 | 1247 |
1207 uint32_t flags = fLoadGlyphFlags; | 1248 uint32_t flags = fLoadGlyphFlags; |
1208 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get
the outline | 1249 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get
the outline |
1209 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) | 1250 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) |
1210 | 1251 |
| 1252 // FreeType glyph slot will be invalid for generateImage |
| 1253 fFaceRec->fGlyphLoaded = 0; |
1211 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flag
s); | 1254 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flag
s); |
1212 | 1255 |
1213 if (err != 0) { | 1256 if (err != 0) { |
1214 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%
d flags:%d) returned 0x%x\n", | 1257 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%
d flags:%d) returned 0x%x\n", |
1215 glyph.getGlyphID(fBaseGlyphCount), flags, err)); | 1258 glyph.getGlyphID(fBaseGlyphCount), flags, err)); |
1216 path->reset(); | 1259 path->reset(); |
1217 return; | 1260 return; |
1218 } | 1261 } |
| 1262 emboldenIfNeeded(fFace, fFace->glyph); |
1219 | 1263 |
1220 generateGlyphPath(fFace, path); | 1264 generateGlyphPath(fFace, path); |
1221 | 1265 |
1222 // The path's origin from FreeType is always the horizontal layout origin. | 1266 // The path's origin from FreeType is always the horizontal layout origin. |
1223 // Offset the path so that it is relative to the vertical origin if needed. | 1267 // Offset the path so that it is relative to the vertical origin if needed. |
1224 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1268 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1225 FT_Vector vector; | 1269 FT_Vector vector; |
1226 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; | 1270 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; |
1227 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; | 1271 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; |
1228 FT_Vector_Transform(&vector, &fMatrix22); | 1272 FT_Vector_Transform(&vector, &fMatrix22); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 ys[4] = leading; | 1323 ys[4] = leading; |
1280 ys[5] = os2 ? os2->xAvgCharWidth : 0; | 1324 ys[5] = os2 ? os2->xAvgCharWidth : 0; |
1281 | 1325 |
1282 SkScalar x_height; | 1326 SkScalar x_height; |
1283 if (os2 && os2->sxHeight) { | 1327 if (os2 && os2->sxHeight) { |
1284 x_height = fScale.x() * os2->sxHeight / upem; | 1328 x_height = fScale.x() * os2->sxHeight / upem; |
1285 } else { | 1329 } else { |
1286 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); | 1330 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); |
1287 if (x_glyph) { | 1331 if (x_glyph) { |
1288 FT_BBox bbox; | 1332 FT_BBox bbox; |
| 1333 // just set the glyph to be invalid for generateImage |
| 1334 fFaceRec->fGlyphLoaded = 0; |
1289 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); | 1335 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); |
1290 if (fRec.fFlags & kEmbolden_Flag) { | 1336 emboldenIfNeeded(fFace, fFace->glyph); |
1291 emboldenOutline(fFace, &fFace->glyph->outline); | |
1292 } | |
1293 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); | 1337 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); |
1294 x_height = bbox.yMax / 64.0f; | 1338 x_height = bbox.yMax / 64.0f; |
1295 } else { | 1339 } else { |
1296 x_height = 0; | 1340 x_height = 0; |
1297 } | 1341 } |
1298 } | 1342 } |
1299 | 1343 |
1300 // convert upem-y values into scalar points | 1344 // convert upem-y values into scalar points |
1301 for (int i = 0; i < 6; i++) { | 1345 for (int i = 0; i < 6; i++) { |
1302 SkScalar y = scaleY * ys[i] / upem; | 1346 SkScalar y = scaleY * ys[i] / upem; |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 *style = (SkTypeface::Style) tempStyle; | 1567 *style = (SkTypeface::Style) tempStyle; |
1524 } | 1568 } |
1525 if (isFixedPitch) { | 1569 if (isFixedPitch) { |
1526 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1570 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
1527 } | 1571 } |
1528 | 1572 |
1529 FT_Done_Face(face); | 1573 FT_Done_Face(face); |
1530 FT_Done_FreeType(library); | 1574 FT_Done_FreeType(library); |
1531 return true; | 1575 return true; |
1532 } | 1576 } |
OLD | NEW |