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