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