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