Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: src/ports/SkFontHost_FreeType.cpp

Issue 23684041: improve bitmap font support (FreeType only) (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698