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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 | |
61 //#define ENABLE_GLYPH_SPEW // for tracing calls | 69 //#define ENABLE_GLYPH_SPEW // for tracing calls |
62 //#define DUMP_STRIKE_CREATION | 70 //#define DUMP_STRIKE_CREATION |
63 | 71 |
64 //#define SK_GAMMA_APPLY_TO_A8 | 72 //#define SK_GAMMA_APPLY_TO_A8 |
65 | 73 |
74 //#define DEBUG_METRICS | |
75 | |
66 using namespace skia_advanced_typeface_metrics_utils; | 76 using namespace skia_advanced_typeface_metrics_utils; |
67 | 77 |
68 static bool isLCD(const SkScalerContext::Rec& rec) { | 78 static bool isLCD(const SkScalerContext::Rec& rec) { |
69 switch (rec.fMaskFormat) { | 79 switch (rec.fMaskFormat) { |
70 case SkMask::kLCD16_Format: | 80 case SkMask::kLCD16_Format: |
71 case SkMask::kLCD32_Format: | 81 case SkMask::kLCD32_Format: |
72 return true; | 82 return true; |
73 default: | 83 default: |
74 return false; | 84 return false; |
75 } | 85 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; | 187 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; |
178 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; | 188 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; |
179 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, | 189 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, |
180 SkPaint::FontMetrics* my) SK_OVERRIDE; | 190 SkPaint::FontMetrics* my) SK_OVERRIDE; |
181 virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE; | 191 virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE; |
182 | 192 |
183 private: | 193 private: |
184 SkFaceRec* fFaceRec; | 194 SkFaceRec* fFaceRec; |
185 FT_Face fFace; // reference to shared face in gFaceRecHead | 195 FT_Face fFace; // reference to shared face in gFaceRecHead |
186 FT_Size fFTSize; // our own copy | 196 FT_Size fFTSize; // our own copy |
197 FT_Int fStrikeIndex; | |
187 SkFixed fScaleX, fScaleY; | 198 SkFixed fScaleX, fScaleY; |
188 FT_Matrix fMatrix22; | 199 FT_Matrix fMatrix22; |
189 uint32_t fLoadGlyphFlags; | 200 uint32_t fLoadGlyphFlags; |
190 bool fDoLinearMetrics; | 201 bool fDoLinearMetrics; |
191 bool fLCDIsVert; | 202 bool fLCDIsVert; |
192 | 203 |
193 // Need scalar versions for generateFontMetrics | 204 // Need scalar versions for generateFontMetrics |
194 SkVector fScale; | 205 SkVector fScale; |
195 SkMatrix fMatrix22Scalar; | 206 SkMatrix fMatrix22Scalar; |
196 | 207 |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], | 753 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], |
743 FT_KERNING_UNSCALED, &delta); | 754 FT_KERNING_UNSCALED, &delta); |
744 if (err) { | 755 if (err) { |
745 return false; | 756 return false; |
746 } | 757 } |
747 adjustments[i] = delta.x; | 758 adjustments[i] = delta.x; |
748 } | 759 } |
749 return true; | 760 return true; |
750 } | 761 } |
751 | 762 |
763 #ifdef DEBUG_METRICS | |
764 static void dumpFTFaceMetrics(const FT_Face face) { | |
765 SkASSERT(face); | |
766 SkDebugf(" units_per_EM: %hu\n", face->units_per_EM); | |
767 SkDebugf(" ascender: %hd\n", face->ascender); | |
768 SkDebugf(" descender: %hd\n", face->descender); | |
769 SkDebugf(" height: %hd\n", face->height); | |
770 SkDebugf(" max_advance_width: %hd\n", face->max_advance_width); | |
771 SkDebugf(" max_advance_height: %hd\n", face->max_advance_height); | |
772 } | |
773 | |
774 static void dumpFTSize(const FT_Size size) { | |
775 SkASSERT(size); | |
776 SkDebugf(" x_ppem: %hu\n", size->metrics.x_ppem); | |
777 SkDebugf(" y_ppem: %hu\n", size->metrics.y_ppem); | |
778 SkDebugf(" x_scale: %f\n", size->metrics.x_scale / 65536.0f); | |
779 SkDebugf(" y_scale: %f\n", size->metrics.y_scale / 65536.0f); | |
780 SkDebugf(" ascender: %f\n", size->metrics.ascender / 64.0f); | |
781 SkDebugf(" descender: %f\n", size->metrics.descender / 64.0f); | |
782 SkDebugf(" height: %f\n", size->metrics.height / 64.0f); | |
783 SkDebugf(" max_advance: %f\n", size->metrics.max_advance / 64.0f); | |
784 } | |
785 | |
786 static void dumpBitmapStrikeMetrics(const FT_Face face, int strikeIndex) { | |
787 SkASSERT(face); | |
788 SkASSERT(strikeIndex >= 0 && strikeIndex < face->num_fixed_sizes); | |
789 SkDebugf(" height: %hd\n", face->available_sizes[strikeIndex].height); | |
790 SkDebugf(" width: %hd\n", face->available_sizes[strikeIndex].width); | |
791 SkDebugf(" size: %f\n", face->available_sizes[strikeIndex].size / 64.0f); | |
792 SkDebugf(" x_ppem: %f\n", face->available_sizes[strikeIndex].x_ppem / 64.0f ); | |
793 SkDebugf(" y_ppem: %f\n", face->available_sizes[strikeIndex].y_ppem / 64.0f ); | |
794 } | |
795 | |
796 static void dumpSkFontMetrics(const SkPaint::FontMetrics& metrics) { | |
797 SkDebugf(" fTop: %f\n", metrics.fTop); | |
798 SkDebugf(" fAscent: %f\n", metrics.fAscent); | |
799 SkDebugf(" fDescent: %f\n", metrics.fDescent); | |
800 SkDebugf(" fBottom: %f\n", metrics.fBottom); | |
801 SkDebugf(" fLeading: %f\n", metrics.fLeading); | |
802 SkDebugf(" fAvgCharWidth: %f\n", metrics.fAvgCharWidth); | |
803 SkDebugf(" fXMin: %f\n", metrics.fXMin); | |
804 SkDebugf(" fXMax: %f\n", metrics.fXMax); | |
805 SkDebugf(" fXHeight: %f\n", metrics.fXHeight); | |
806 } | |
807 | |
808 static void dumpSkGlyphMetrics(const SkGlyph& glyph) { | |
809 SkDebugf(" fAdvanceX: %f\n", SkFixedToScalar(glyph.fAdvanceX)); | |
810 SkDebugf(" fAdvanceY: %f\n", SkFixedToScalar(glyph.fAdvanceY)); | |
811 SkDebugf(" fWidth: %hu\n", glyph.fWidth); | |
812 SkDebugf(" fHeight: %hu\n", glyph.fHeight); | |
813 SkDebugf(" fTop: %hd\n", glyph.fTop); | |
814 SkDebugf(" fLeft: %hd\n", glyph.fLeft); | |
815 } | |
816 #endif | |
817 | |
818 static FT_Int chooseBitmapStrike(FT_Face face, SkFixed scaleY) { | |
819 // early out if face is bad | |
820 if (face == NULL) { | |
821 SkDEBUGF(("chooseBitmapStrike aborted due to NULL face\n")); | |
822 return -1; | |
823 } | |
824 // determine target ppem | |
825 FT_Pos targetPPEM = SkFixedToFDot6(scaleY); | |
826 // find a bitmap strike equal to or just larger than the requested size | |
827 FT_Int chosenStrikeIndex = -1; | |
828 FT_Pos chosenPPEM = 0; | |
829 for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIn dex) { | |
830 FT_Pos thisPPEM = face->available_sizes[strikeIndex].y_ppem; | |
831 if (thisPPEM == targetPPEM) { | |
832 // exact match - our search stops here | |
833 chosenPPEM = thisPPEM; | |
834 chosenStrikeIndex = strikeIndex; | |
835 break; | |
836 } else if (chosenPPEM < targetPPEM) { | |
837 // attempt to increase chosenPPEM | |
838 if (thisPPEM > chosenPPEM) { | |
839 chosenPPEM = thisPPEM; | |
840 chosenStrikeIndex = strikeIndex; | |
841 } | |
842 } else { | |
843 // attempt to decrease chosenPPEM, but not below targetPPEM | |
844 if (thisPPEM < chosenPPEM && thisPPEM > targetPPEM) { | |
845 chosenPPEM = thisPPEM; | |
846 chosenStrikeIndex = strikeIndex; | |
847 } | |
848 } | |
849 } | |
850 if (chosenStrikeIndex != -1) { | |
851 // use the chosen strike | |
852 #ifdef DEBUG_METRICS | |
853 SkDebugf("chooseBitmapStrike: chose strike %d for face \"%s\" at size %f \n", | |
854 chosenStrikeIndex, face->family_name, SkFixedToScalar(scaleY)); | |
855 dumpBitmapStrikeMetrics(face, chosenStrikeIndex); | |
856 #endif | |
857 FT_Error err = FT_Select_Size(face, chosenStrikeIndex); | |
858 if (err != 0) { | |
859 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_nam e, | |
860 chosenStrikeIndex, err)); | |
861 chosenStrikeIndex = -1; | |
862 } | |
863 } | |
864 return chosenStrikeIndex; | |
865 } | |
866 | |
752 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, | 867 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, |
753 const SkDescriptor* desc) | 868 const SkDescriptor* desc) |
754 : SkScalerContext_FreeType_Base(typeface, desc) { | 869 : SkScalerContext_FreeType_Base(typeface, desc) { |
755 SkAutoMutexAcquire ac(gFTMutex); | 870 SkAutoMutexAcquire ac(gFTMutex); |
756 | 871 |
757 if (gFTCount == 0) { | 872 if (gFTCount == 0) { |
758 if (!InitFreetype()) { | 873 if (!InitFreetype()) { |
759 sk_throw(); | 874 sk_throw(); |
760 } | 875 } |
761 } | 876 } |
762 ++gFTCount; | 877 ++gFTCount; |
763 | 878 |
764 // load the font file | 879 // load the font file |
880 fStrikeIndex = -1; | |
765 fFTSize = NULL; | 881 fFTSize = NULL; |
766 fFace = NULL; | 882 fFace = NULL; |
767 fFaceRec = ref_ft_face(typeface); | 883 fFaceRec = ref_ft_face(typeface); |
768 if (NULL == fFaceRec) { | 884 if (NULL == fFaceRec) { |
769 return; | 885 return; |
770 } | 886 } |
771 fFace = fFaceRec->fFace; | 887 fFace = fFaceRec->fFace; |
772 | 888 |
773 // compute our factors from the record | 889 // compute our factors from the record |
774 | 890 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
814 fMatrix22.xx = fMatrix22.yy = SK_Fixed1; | 930 fMatrix22.xx = fMatrix22.yy = SK_Fixed1; |
815 fMatrix22.xy = fMatrix22.yx = 0; | 931 fMatrix22.xy = fMatrix22.yx = 0; |
816 } | 932 } |
817 fScale.set(sx, sy); | 933 fScale.set(sx, sy); |
818 fScaleX = SkScalarToFixed(sx); | 934 fScaleX = SkScalarToFixed(sx); |
819 fScaleY = SkScalarToFixed(sy); | 935 fScaleY = SkScalarToFixed(sy); |
820 | 936 |
821 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); | 937 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); |
822 | 938 |
823 // compute the flags we send to Load_Glyph | 939 // compute the flags we send to Load_Glyph |
940 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositi oning_Flag); | |
824 { | 941 { |
825 FT_Int32 loadFlags = FT_LOAD_DEFAULT; | 942 FT_Int32 loadFlags = FT_LOAD_DEFAULT; |
826 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPo sitioning_Flag); | |
827 | 943 |
828 if (SkMask::kBW_Format == fRec.fMaskFormat) { | 944 if (SkMask::kBW_Format == fRec.fMaskFormat) { |
829 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 | 945 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 |
830 loadFlags = FT_LOAD_TARGET_MONO; | 946 loadFlags = FT_LOAD_TARGET_MONO; |
831 if (fRec.getHinting() == SkPaint::kNo_Hinting) { | 947 if (fRec.getHinting() == SkPaint::kNo_Hinting) { |
832 loadFlags = FT_LOAD_NO_HINTING; | 948 loadFlags = FT_LOAD_NO_HINTING; |
833 linearMetrics = true; | 949 linearMetrics = true; |
834 } | 950 } |
835 } else { | 951 } else { |
836 switch (fRec.getHinting()) { | 952 switch (fRec.getHinting()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
874 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct | 990 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct |
875 // advances, as fontconfig and cairo do. | 991 // advances, as fontconfig and cairo do. |
876 // See http://code.google.com/p/skia/issues/detail?id=222. | 992 // See http://code.google.com/p/skia/issues/detail?id=222. |
877 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; | 993 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; |
878 | 994 |
879 // Use vertical layout if requested. | 995 // Use vertical layout if requested. |
880 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 996 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
881 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; | 997 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; |
882 } | 998 } |
883 | 999 |
1000 loadFlags |= FT_LOAD_COLOR; | |
bungeman-skia
2013/11/27 00:04:49
We should actually check FT_HAS_COLOR(face) and se
| |
1001 | |
884 fLoadGlyphFlags = loadFlags; | 1002 fLoadGlyphFlags = loadFlags; |
885 fDoLinearMetrics = linearMetrics; | |
886 } | 1003 } |
887 | 1004 |
888 // now create the FT_Size | 1005 FT_Error err = FT_New_Size(fFace, &fFTSize); |
1006 if (err != 0) { | |
1007 SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, fFace->family_na me)); | |
1008 fFace = NULL; | |
1009 return; | |
1010 } | |
1011 err = FT_Activate_Size(fFTSize); | |
1012 if (err != 0) { | |
1013 SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", fFace, f ScaleX, fScaleY, | |
1014 err)); | |
1015 fFTSize = NULL; | |
1016 return; | |
1017 } | |
889 | 1018 |
890 { | 1019 if (fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) { |
891 FT_Error err; | 1020 fStrikeIndex = chooseBitmapStrike(fFace, fScaleY); |
1021 } | |
892 | 1022 |
893 err = FT_New_Size(fFace, &fFTSize); | 1023 if (fStrikeIndex == -1) { |
894 if (err != 0) { | 1024 if (fFace->face_flags & FT_FACE_FLAG_SCALABLE) { |
895 SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Si ze(0x%x, 0x%x) returned 0x%x\n", | 1025 err = FT_Set_Char_Size(fFace, |
896 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 1026 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScal eY), |
897 fFace = NULL; | 1027 72, 72); |
898 return; | 1028 if (err != 0) { |
1029 SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n", f Face, fScaleX, | |
1030 fScaleY, err)); | |
1031 fFace = NULL; | |
1032 return; | |
1033 } | |
1034 FT_Set_Transform(fFace, &fMatrix22, NULL); | |
1035 } else { | |
1036 SkDEBUGF(("no glyphs for font \"%s\" size %f?\n", fFace->family_name , | |
1037 SkFixedToScalar(fScaleY))); | |
899 } | 1038 } |
900 | 1039 } else { |
901 err = FT_Activate_Size(fFTSize); | 1040 linearMetrics = false; // no linear metrics for bitmap fonts |
902 if (err != 0) { | |
903 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x ) returned 0x%x\n", | |
904 fFaceRec->fFontID, fScaleX, fScaleY, err)); | |
905 fFTSize = NULL; | |
906 } | |
907 | |
908 err = FT_Set_Char_Size( fFace, | |
909 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY) , | |
910 72, 72); | |
911 if (err != 0) { | |
912 SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x ) returned 0x%x\n", | |
913 fFaceRec->fFontID, fScaleX, fScaleY, err)); | |
914 fFace = NULL; | |
915 return; | |
916 } | |
917 | |
918 FT_Set_Transform( fFace, &fMatrix22, NULL); | |
919 } | 1041 } |
1042 fDoLinearMetrics = linearMetrics; | |
920 } | 1043 } |
921 | 1044 |
922 SkScalerContext_FreeType::~SkScalerContext_FreeType() { | 1045 SkScalerContext_FreeType::~SkScalerContext_FreeType() { |
923 SkAutoMutexAcquire ac(gFTMutex); | 1046 SkAutoMutexAcquire ac(gFTMutex); |
924 | 1047 |
925 if (fFTSize != NULL) { | 1048 if (fFTSize != NULL) { |
926 FT_Done_Size(fFTSize); | 1049 FT_Done_Size(fFTSize); |
927 } | 1050 } |
928 | 1051 |
929 if (fFace != NULL) { | 1052 if (fFace != NULL) { |
930 unref_ft_face(fFace); | 1053 unref_ft_face(fFace); |
931 } | 1054 } |
932 if (--gFTCount == 0) { | 1055 if (--gFTCount == 0) { |
933 // SkDEBUGF(("FT_Done_FreeType\n")); | 1056 // SkDEBUGF(("FT_Done_FreeType\n")); |
934 FT_Done_FreeType(gFTLibrary); | 1057 FT_Done_FreeType(gFTLibrary); |
935 SkDEBUGCODE(gFTLibrary = NULL;) | 1058 SkDEBUGCODE(gFTLibrary = NULL;) |
936 } | 1059 } |
937 } | 1060 } |
938 | 1061 |
939 /* We call this before each use of the fFace, since we may be sharing | 1062 /* We call this before each use of the fFace, since we may be sharing |
940 this face with other context (at different sizes). | 1063 this face with other context (at different sizes). |
941 */ | 1064 */ |
942 FT_Error SkScalerContext_FreeType::setupSize() { | 1065 FT_Error SkScalerContext_FreeType::setupSize() { |
943 FT_Error err = FT_Activate_Size(fFTSize); | 1066 FT_Error err = FT_Activate_Size(fFTSize); |
944 | |
945 if (err != 0) { | 1067 if (err != 0) { |
946 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re turned 0x%x\n", | 1068 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re turned 0x%x\n", |
947 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 1069 fFaceRec->fFontID, fScaleX, fScaleY, err)); |
948 fFTSize = NULL; | 1070 fFTSize = NULL; |
949 } else { | 1071 return err; |
950 // seems we need to reset this every time (not sure why, but without it | |
951 // I get random italics from some other fFTSize) | |
952 FT_Set_Transform( fFace, &fMatrix22, NULL); | |
953 } | 1072 } |
954 return err; | 1073 |
1074 // seems we need to reset this every time (not sure why, but without it | |
1075 // I get random italics from some other fFTSize) | |
1076 FT_Set_Transform(fFace, &fMatrix22, NULL); | |
1077 return 0; | |
955 } | 1078 } |
956 | 1079 |
957 unsigned SkScalerContext_FreeType::generateGlyphCount() { | 1080 unsigned SkScalerContext_FreeType::generateGlyphCount() { |
958 return fFace->num_glyphs; | 1081 return fFace->num_glyphs; |
959 } | 1082 } |
960 | 1083 |
961 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { | 1084 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { |
962 return SkToU16(FT_Get_Char_Index( fFace, uni )); | 1085 return SkToU16(FT_Get_Char_Index( fFace, uni )); |
963 } | 1086 } |
964 | 1087 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1054 if (fLCDIsVert) { | 1177 if (fLCDIsVert) { |
1055 glyph->fHeight += gLCDExtra; | 1178 glyph->fHeight += gLCDExtra; |
1056 glyph->fTop -= gLCDExtra >> 1; | 1179 glyph->fTop -= gLCDExtra >> 1; |
1057 } else { | 1180 } else { |
1058 glyph->fWidth += gLCDExtra; | 1181 glyph->fWidth += gLCDExtra; |
1059 glyph->fLeft -= gLCDExtra >> 1; | 1182 glyph->fLeft -= gLCDExtra >> 1; |
1060 } | 1183 } |
1061 } | 1184 } |
1062 } | 1185 } |
1063 | 1186 |
1187 inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) { | |
1188 glyph.fWidth *= scale; | |
1189 glyph.fHeight *= scale; | |
1190 glyph.fTop *= scale; | |
1191 glyph.fLeft *= scale; | |
1192 | |
1193 SkFixed fixedScale = SkScalarToFixed(scale); | |
1194 glyph.fAdvanceX = SkFixedMul(glyph.fAdvanceX, fixedScale); | |
1195 glyph.fAdvanceY = SkFixedMul(glyph.fAdvanceY, fixedScale); | |
1196 } | |
1197 | |
1064 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { | 1198 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { |
1065 SkAutoMutexAcquire ac(gFTMutex); | 1199 SkAutoMutexAcquire ac(gFTMutex); |
1066 | 1200 |
1067 glyph->fRsbDelta = 0; | 1201 glyph->fRsbDelta = 0; |
1068 glyph->fLsbDelta = 0; | 1202 glyph->fLsbDelta = 0; |
1069 | 1203 |
1070 FT_Error err; | 1204 FT_Error err; |
1071 | 1205 |
1072 if (this->setupSize()) { | 1206 if (this->setupSize()) { |
1073 goto ERROR; | 1207 goto ERROR; |
1074 } | 1208 } |
1075 | 1209 |
1076 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl ags ); | 1210 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl ags ); |
1077 if (err != 0) { | 1211 if (err != 0) { |
1078 #if 0 | 1212 #if 0 |
1079 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph( glyph:%d flags:%x) returned 0x%x\n", | 1213 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph( glyph:%d flags:%x) returned 0x%x\n", |
1080 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad GlyphFlags, err)); | 1214 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad GlyphFlags, err)); |
1081 #endif | 1215 #endif |
1082 ERROR: | 1216 ERROR: |
1083 glyph->zeroMetrics(); | 1217 glyph->zeroMetrics(); |
1084 return; | 1218 return; |
1085 } | 1219 } |
1086 | 1220 |
1087 switch ( fFace->glyph->format ) { | 1221 switch ( fFace->glyph->format ) { |
1088 case FT_GLYPH_FORMAT_OUTLINE: { | 1222 case FT_GLYPH_FORMAT_OUTLINE: |
1089 FT_BBox bbox; | |
1090 | |
1091 if (0 == fFace->glyph->outline.n_contours) { | 1223 if (0 == fFace->glyph->outline.n_contours) { |
1092 glyph->fWidth = 0; | 1224 glyph->fWidth = 0; |
1093 glyph->fHeight = 0; | 1225 glyph->fHeight = 0; |
1094 glyph->fTop = 0; | 1226 glyph->fTop = 0; |
1095 glyph->fLeft = 0; | 1227 glyph->fLeft = 0; |
1096 break; | 1228 } else { |
1229 if (fRec.fFlags & kEmbolden_Flag && !(fFace->style_flags & FT_STYLE_ FLAG_BOLD)) { | |
1230 emboldenOutline(fFace, &fFace->glyph->outline); | |
1231 } | |
1232 | |
1233 FT_BBox bbox; | |
1234 getBBoxForCurrentGlyph(glyph, &bbox, true); | |
1235 | |
1236 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); | |
1237 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); | |
1238 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); | |
1239 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); | |
1240 | |
1241 updateGlyphIfLCD(glyph); | |
1097 } | 1242 } |
1098 | |
1099 if (fRec.fFlags & kEmbolden_Flag) { | |
1100 emboldenOutline(fFace, &fFace->glyph->outline); | |
1101 } | |
1102 | |
1103 getBBoxForCurrentGlyph(glyph, &bbox, true); | |
1104 | |
1105 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); | |
1106 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); | |
1107 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); | |
1108 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); | |
1109 | |
1110 updateGlyphIfLCD(glyph); | |
1111 | |
1112 break; | 1243 break; |
1113 } | |
1114 | 1244 |
1115 case FT_GLYPH_FORMAT_BITMAP: | 1245 case FT_GLYPH_FORMAT_BITMAP: |
1116 if (fRec.fFlags & kEmbolden_Flag) { | 1246 if (fRec.fFlags & kEmbolden_Flag) { |
1117 FT_GlyphSlot_Own_Bitmap(fFace->glyph); | 1247 FT_GlyphSlot_Own_Bitmap(fFace->glyph); |
1118 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmbolde nStrength, 0); | 1248 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmbolde nStrength, 0); |
1119 } | 1249 } |
1120 | 1250 |
1121 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1251 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1122 FT_Vector vector; | 1252 FT_Vector vector; |
1123 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric s.horiBearingX; | 1253 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric s.horiBearingX; |
1124 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri cs.horiBearingY; | 1254 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri cs.horiBearingY; |
1125 FT_Vector_Transform(&vector, &fMatrix22); | 1255 FT_Vector_Transform(&vector, &fMatrix22); |
1126 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); | 1256 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); |
1127 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); | 1257 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); |
1128 } | 1258 } |
1129 | 1259 |
1260 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { | |
1261 glyph->fMaskFormat = SkMask::kARGB32_Format; | |
1262 } | |
1263 | |
1130 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); | 1264 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); |
1131 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); | 1265 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); |
1132 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); | 1266 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); |
1133 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); | 1267 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); |
1134 break; | 1268 break; |
1135 | 1269 |
1136 default: | 1270 default: |
1137 SkDEBUGFAIL("unknown glyph format"); | 1271 SkDEBUGFAIL("unknown glyph format"); |
1138 goto ERROR; | 1272 goto ERROR; |
1139 } | 1273 } |
(...skipping 14 matching lines...) Expand all Loading... | |
1154 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); | 1288 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); |
1155 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); | 1289 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); |
1156 | 1290 |
1157 if (fRec.fFlags & kDevKernText_Flag) { | 1291 if (fRec.fFlags & kDevKernText_Flag) { |
1158 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); | 1292 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); |
1159 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); | 1293 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); |
1160 } | 1294 } |
1161 } | 1295 } |
1162 } | 1296 } |
1163 | 1297 |
1298 if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP && fScaleY && fFace->size ->metrics.y_ppem) { | |
1299 #ifdef DEBUG_METRICS | |
1300 SkDebugf("pre-scale glyph metrics:\n"); | |
1301 dumpSkGlyphMetrics(*glyph); | |
1302 #endif | |
1303 // NOTE: both dimensions are scaled by y_ppem. this is WAI. | |
1304 scaleGlyphMetrics(*glyph, SkScalarDiv(SkFixedToScalar(fScaleY), | |
1305 SkIntToScalar(fFace->size->metrics .y_ppem))); | |
1306 } | |
1307 #ifdef DEBUG_METRICS | |
1308 SkDebugf("post-scale glyph metrics:\n"); | |
1309 dumpSkGlyphMetrics(*glyph); | |
1310 #endif | |
1311 | |
1164 | 1312 |
1165 #ifdef ENABLE_GLYPH_SPEW | 1313 #ifdef ENABLE_GLYPH_SPEW |
1166 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); | 1314 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); |
1167 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyp hCount), fLoadGlyphFlags, glyph->fWidth)); | 1315 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyp hCount), fLoadGlyphFlags, glyph->fWidth)); |
1168 #endif | 1316 #endif |
1169 } | 1317 } |
1170 | 1318 |
1171 | 1319 |
1172 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { | 1320 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { |
1173 SkAutoMutexAcquire ac(gFTMutex); | 1321 SkAutoMutexAcquire ac(gFTMutex); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1221 // Offset the path so that it is relative to the vertical origin if needed. | 1369 // Offset the path so that it is relative to the vertical origin if needed. |
1222 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1370 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1223 FT_Vector vector; | 1371 FT_Vector vector; |
1224 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho riBearingX; | 1372 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho riBearingX; |
1225 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h oriBearingY; | 1373 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h oriBearingY; |
1226 FT_Vector_Transform(&vector, &fMatrix22); | 1374 FT_Vector_Transform(&vector, &fMatrix22); |
1227 path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y)); | 1375 path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y)); |
1228 } | 1376 } |
1229 } | 1377 } |
1230 | 1378 |
1231 void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, | 1379 #ifdef DEBUG_METRICS |
1232 SkPaint::FontMetrics* my) { | 1380 void generateFontMetricsOLD(FT_Face face, SkScalar scaleX, SkScalar scaleY, |
1381 uint32_t loadGlyphFlags, uint16_t recFlags, SkMatrix matrix22Scalar, | |
1382 SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) { | |
1233 if (NULL == mx && NULL == my) { | 1383 if (NULL == mx && NULL == my) { |
1234 return; | 1384 return; |
1235 } | 1385 } |
1236 | 1386 |
1237 SkAutoMutexAcquire ac(gFTMutex); | 1387 if (false) { |
1238 | 1388 ERROR: |
1239 if (this->setupSize()) { | |
1240 ERROR: | |
1241 if (mx) { | 1389 if (mx) { |
1242 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); | 1390 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); |
1243 } | 1391 } |
1244 if (my) { | 1392 if (my) { |
1245 sk_bzero(my, sizeof(SkPaint::FontMetrics)); | 1393 sk_bzero(my, sizeof(SkPaint::FontMetrics)); |
1246 } | 1394 } |
1247 return; | 1395 return; |
1248 } | 1396 } |
1249 | 1397 |
1250 FT_Face face = fFace; | |
1251 int upem = face->units_per_EM; | 1398 int upem = face->units_per_EM; |
1252 if (upem <= 0) { | 1399 if (upem <= 0) { |
1253 goto ERROR; | 1400 goto ERROR; |
1254 } | 1401 } |
1255 | 1402 |
1256 SkPoint pts[6]; | 1403 SkPoint pts[6]; |
1257 SkFixed ys[6]; | 1404 SkFixed ys[6]; |
1258 SkScalar scaleY = fScale.y(); | 1405 SkScalar mxy = matrix22Scalar.getSkewX(); |
1259 SkScalar mxy = fMatrix22Scalar.getSkewX(); | 1406 SkScalar myy = matrix22Scalar.getScaleY(); |
1260 SkScalar myy = fMatrix22Scalar.getScaleY(); | |
1261 SkScalar xmin = SkIntToScalar(face->bbox.xMin) / upem; | 1407 SkScalar xmin = SkIntToScalar(face->bbox.xMin) / upem; |
1262 SkScalar xmax = SkIntToScalar(face->bbox.xMax) / upem; | 1408 SkScalar xmax = SkIntToScalar(face->bbox.xMax) / upem; |
1263 | 1409 |
1264 int leading = face->height - (face->ascender + -face->descender); | 1410 int leading = face->height - (face->ascender + -face->descender); |
1265 if (leading < 0) { | 1411 if (leading < 0) { |
1266 leading = 0; | 1412 leading = 0; |
1267 } | 1413 } |
1268 | 1414 |
1269 // Try to get the OS/2 table from the font. This contains the specific | |
1270 // average font width metrics which Windows uses. | |
1271 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); | 1415 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
1272 | 1416 |
1273 ys[0] = -face->bbox.yMax; | 1417 ys[0] = -face->bbox.yMax; |
1274 ys[1] = -face->ascender; | 1418 ys[1] = -face->ascender; |
1275 ys[2] = -face->descender; | 1419 ys[2] = -face->descender; |
1276 ys[3] = -face->bbox.yMin; | 1420 ys[3] = -face->bbox.yMin; |
1277 ys[4] = leading; | 1421 ys[4] = leading; |
1278 ys[5] = os2 ? os2->xAvgCharWidth : 0; | 1422 ys[5] = os2 ? os2->xAvgCharWidth : 0; |
1279 | 1423 |
1280 SkScalar x_height; | 1424 SkScalar x_height; |
1281 if (os2 && os2->sxHeight) { | 1425 if (os2 && os2->sxHeight) { |
1282 x_height = fScale.x() * os2->sxHeight / upem; | 1426 x_height = scaleX * os2->sxHeight / upem; |
1283 } else { | 1427 } else { |
1284 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); | 1428 const FT_UInt x_glyph = FT_Get_Char_Index(face, 'x'); |
1285 if (x_glyph) { | 1429 if (x_glyph) { |
1286 FT_BBox bbox; | 1430 FT_BBox bbox; |
1287 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); | 1431 FT_Load_Glyph(face, x_glyph, loadGlyphFlags); |
1288 if (fRec.fFlags & kEmbolden_Flag) { | 1432 if (recFlags & SkScalerContext::kEmbolden_Flag) { |
1289 emboldenOutline(fFace, &fFace->glyph->outline); | 1433 SkDebugf("x_height is incorrect (skipped embolden step)\n"); |
1290 } | 1434 } |
1291 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); | 1435 FT_Outline_Get_CBox(&face->glyph->outline, &bbox); |
1292 x_height = bbox.yMax / 64.0f; | 1436 x_height = bbox.yMax / 64.0f; |
1293 } else { | 1437 } else { |
1294 x_height = 0; | 1438 x_height = 0; |
1295 } | 1439 } |
1296 } | 1440 } |
1297 | 1441 |
1298 // convert upem-y values into scalar points | |
1299 for (int i = 0; i < 6; i++) { | 1442 for (int i = 0; i < 6; i++) { |
1300 SkScalar y = scaleY * ys[i] / upem; | 1443 SkScalar y = scaleY * ys[i] / upem; |
1301 pts[i].set(y * mxy, y * myy); | 1444 pts[i].set(y * mxy, y * myy); |
1302 } | 1445 } |
1303 | 1446 |
1304 if (mx) { | 1447 if (mx) { |
1305 mx->fTop = pts[0].fX; | 1448 mx->fTop = pts[0].fX; |
1306 mx->fAscent = pts[1].fX; | 1449 mx->fAscent = pts[1].fX; |
1307 mx->fDescent = pts[2].fX; | 1450 mx->fDescent = pts[2].fX; |
1308 mx->fBottom = pts[3].fX; | 1451 mx->fBottom = pts[3].fX; |
1309 mx->fLeading = pts[4].fX; | 1452 mx->fLeading = pts[4].fX; |
1310 mx->fAvgCharWidth = pts[5].fX; | 1453 mx->fAvgCharWidth = pts[5].fX; |
1311 mx->fXMin = xmin; | 1454 mx->fXMin = xmin; |
1312 mx->fXMax = xmax; | 1455 mx->fXMax = xmax; |
1313 mx->fXHeight = x_height; | 1456 mx->fXHeight = x_height; |
1314 } | 1457 SkDebugf("generateFontMetricsOLD(\"%s\"): mx is:\n", face->family_name); |
1315 if (my) { | 1458 dumpSkFontMetrics(*mx); |
1459 } | |
1460 | |
1461 if (my) { | |
1316 my->fTop = pts[0].fY; | 1462 my->fTop = pts[0].fY; |
1317 my->fAscent = pts[1].fY; | 1463 my->fAscent = pts[1].fY; |
1318 my->fDescent = pts[2].fY; | 1464 my->fDescent = pts[2].fY; |
1319 my->fBottom = pts[3].fY; | 1465 my->fBottom = pts[3].fY; |
1320 my->fLeading = pts[4].fY; | 1466 my->fLeading = pts[4].fY; |
1321 my->fAvgCharWidth = pts[5].fY; | 1467 my->fAvgCharWidth = pts[5].fY; |
1322 my->fXMin = xmin; | 1468 my->fXMin = xmin; |
1323 my->fXMax = xmax; | 1469 my->fXMax = xmax; |
1324 my->fXHeight = x_height; | 1470 my->fXHeight = x_height; |
1471 SkDebugf("generateFontMetricsOLD(\"%s\"): my is:\n", face->family_name); | |
1472 dumpSkFontMetrics(*my); | |
1473 } | |
1474 } | |
1475 #endif | |
1476 | |
1477 void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, | |
1478 SkPaint::FontMetrics* my) { | |
1479 if (NULL == mx && NULL == my) { | |
1480 return; | |
1481 } | |
1482 | |
1483 SkAutoMutexAcquire ac(gFTMutex); | |
1484 | |
1485 if (this->setupSize()) { | |
1486 ERROR: | |
1487 if (mx) { | |
1488 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); | |
1489 } | |
1490 if (my) { | |
1491 sk_bzero(my, sizeof(SkPaint::FontMetrics)); | |
1492 } | |
1493 return; | |
1494 } | |
1495 | |
1496 FT_Face face = fFace; | |
1497 SkScalar scaleX = fScale.x(); | |
1498 SkScalar scaleY = fScale.y(); | |
1499 SkScalar mxy = fMatrix22Scalar.getSkewX() * scaleY; | |
1500 SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY; | |
1501 | |
1502 #ifdef DEBUG_METRICS | |
1503 SkDebugf("generateFontMetrics(\"%s\"):\n", face->family_name); | |
1504 dumpFTFaceMetrics(face); | |
1505 dumpFTSize(face->size); | |
1506 #endif | |
1507 | |
1508 // fetch units/EM from "head" table if needed (ie for bitmap fonts) | |
1509 SkScalar upem = SkIntToScalar(face->units_per_EM); | |
1510 if (!upem) { | |
1511 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); | |
1512 if (ttHeader) { | |
1513 upem = SkIntToScalar(ttHeader->Units_Per_EM); | |
1514 } | |
1515 } | |
1516 | |
1517 // use the os/2 table as a source of reasonable defaults. | |
1518 SkScalar x_height = 0.0f; | |
1519 SkScalar avgCharWidth = 0.0f; | |
1520 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); | |
1521 if (os2) { | |
1522 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; | |
1523 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; | |
1524 } | |
1525 | |
1526 // pull from format-specific metrics as needed | |
1527 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; | |
1528 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font | |
1529 ascent = -SkIntToScalar(face->ascender) / upem; | |
1530 descent = -SkIntToScalar(face->descender) / upem; | |
1531 leading = SkIntToScalar(face->height + (face->descender - face->ascender )) / upem; | |
1532 xmin = SkIntToScalar(face->bbox.xMin) / upem; | |
1533 xmax = SkIntToScalar(face->bbox.xMax) / upem; | |
1534 ymin = -SkIntToScalar(face->bbox.yMin) / upem; | |
1535 ymax = -SkIntToScalar(face->bbox.yMax) / upem; | |
1536 // we may be able to synthesize x_height from outline | |
1537 if (!x_height) { | |
1538 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); | |
1539 if (x_glyph) { | |
1540 FT_BBox bbox; | |
1541 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); | |
1542 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_ STYLE_FLAG_BOLD)) { | |
1543 emboldenOutline(fFace, &fFace->glyph->outline); | |
1544 } | |
1545 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); | |
1546 x_height = SkIntToScalar(bbox.yMax) / 64.0f; | |
1547 } | |
1548 } | |
1549 } else if (fStrikeIndex != -1) { // bitmap strike metrics | |
1550 #ifdef DEBUG_METRICS | |
1551 dumpBitmapStrikeMetrics(fFace, fStrikeIndex); | |
1552 #endif | |
1553 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); | |
1554 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); | |
1555 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); | |
1556 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f ); | |
1557 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) | |
1558 + ascent - descent; | |
1559 xmin = 0.0f; | |
1560 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; | |
1561 ymin = descent + leading; | |
1562 ymax = ascent - descent; | |
1563 if (!x_height) { | |
1564 x_height = -ascent; | |
1565 } | |
1566 if (!avgCharWidth) { | |
1567 avgCharWidth = xmax - xmin; | |
1568 } | |
1569 } else { | |
1570 goto ERROR; | |
1571 } | |
1572 | |
1573 // synthesize elements that were not provided by the os/2 table or format-sp ecific metrics | |
1574 if (!x_height) { | |
1575 x_height = -ascent; | |
1576 } | |
1577 if (!avgCharWidth) { | |
1578 avgCharWidth = xmax - xmin; | |
1579 } | |
1580 | |
1581 // disallow negative linespacing | |
1582 if (leading < 0.0f) { | |
1583 leading = 0.0f; | |
1584 } | |
1585 | |
1586 #ifdef DEBUG_METRICS | |
1587 generateFontMetricsOLD(fFace, fScale.x(), fScale.y(), fLoadGlyphFlags, fRec. fFlags, | |
1588 fMatrix22Scalar, mx, my); | |
1589 #endif | |
1590 if (mx) { | |
1591 mx->fTop = ymax * mxy; | |
1592 mx->fAscent = ascent * mxy; | |
1593 mx->fDescent = descent * mxy; | |
1594 mx->fBottom = ymin * mxy; | |
1595 mx->fLeading = leading * mxy; | |
1596 mx->fAvgCharWidth = avgCharWidth * mxy; | |
1597 mx->fXMin = xmin; | |
1598 mx->fXMax = xmax; | |
1599 mx->fXHeight = x_height; | |
1600 #ifdef DEBUG_METRICS | |
1601 SkDebugf("generateFontMetrics(\"%s\"): mx is:\n", face->family_name); | |
1602 dumpSkFontMetrics(*mx); | |
1603 #endif | |
1604 } | |
1605 if (my) { | |
1606 my->fTop = ymax * myy; | |
1607 my->fAscent = ascent * myy; | |
1608 my->fDescent = descent * myy; | |
1609 my->fBottom = ymin * myy; | |
1610 my->fLeading = leading * myy; | |
1611 my->fAvgCharWidth = avgCharWidth * myy; | |
1612 my->fXMin = xmin; | |
1613 my->fXMax = xmax; | |
1614 my->fXHeight = x_height; | |
1615 #ifdef DEBUG_METRICS | |
1616 SkDebugf("generateFontMetrics(\"%s\"): my is:\n", face->family_name); | |
1617 dumpSkFontMetrics(*my); | |
1618 #endif | |
1325 } | 1619 } |
1326 } | 1620 } |
1327 | 1621 |
1328 /////////////////////////////////////////////////////////////////////////////// | 1622 /////////////////////////////////////////////////////////////////////////////// |
1329 | 1623 |
1330 #include "SkUtils.h" | 1624 #include "SkUtils.h" |
1331 | 1625 |
1332 static SkUnichar next_utf8(const void** chars) { | 1626 static SkUnichar next_utf8(const void** chars) { |
1333 return SkUTF8_NextUnichar((const char**)chars); | 1627 return SkUTF8_NextUnichar((const char**)chars); |
1334 } | 1628 } |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1521 *style = (SkTypeface::Style) tempStyle; | 1815 *style = (SkTypeface::Style) tempStyle; |
1522 } | 1816 } |
1523 if (isFixedPitch) { | 1817 if (isFixedPitch) { |
1524 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1818 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
1525 } | 1819 } |
1526 | 1820 |
1527 FT_Done_Face(face); | 1821 FT_Done_Face(face); |
1528 FT_Done_FreeType(library); | 1822 FT_Done_FreeType(library); |
1529 return true; | 1823 return true; |
1530 } | 1824 } |
OLD | NEW |