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 "SkAdvancedTypefaceMetrics.h" | 9 #include "SkAdvancedTypefaceMetrics.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkCanvas.h" | 11 #include "SkCanvas.h" |
12 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
13 #include "SkDescriptor.h" | 13 #include "SkDescriptor.h" |
14 #include "SkFDot6.h" | 14 #include "SkFDot6.h" |
15 #include "SkFloatingPoint.h" | 15 #include "SkFloatingPoint.h" |
16 #include "SkFontHost.h" | 16 #include "SkFontHost.h" |
17 #include "SkFontHost_FreeType_common.h" | 17 #include "SkFontHost_FreeType_common.h" |
18 #include "SkGlyph.h" | 18 #include "SkGlyph.h" |
19 #include "SkMask.h" | 19 #include "SkMask.h" |
20 #include "SkMaskGamma.h" | 20 #include "SkMaskGamma.h" |
| 21 #include "SkMatrix22.h" |
21 #include "SkOTUtils.h" | 22 #include "SkOTUtils.h" |
22 #include "SkOnce.h" | 23 #include "SkOnce.h" |
23 #include "SkScalerContext.h" | 24 #include "SkScalerContext.h" |
24 #include "SkStream.h" | 25 #include "SkStream.h" |
25 #include "SkString.h" | 26 #include "SkString.h" |
26 #include "SkTemplates.h" | 27 #include "SkTemplates.h" |
27 #include "SkThread.h" | 28 #include "SkThread.h" |
28 | 29 |
29 #if defined(SK_CAN_USE_DLOPEN) | 30 #if defined(SK_CAN_USE_DLOPEN) |
30 #include <dlfcn.h> | 31 #include <dlfcn.h> |
31 #endif | 32 #endif |
32 #include <ft2build.h> | 33 #include <ft2build.h> |
33 #include FT_FREETYPE_H | 34 #include FT_FREETYPE_H |
34 #include FT_OUTLINE_H | 35 #include FT_OUTLINE_H |
35 #include FT_SIZES_H | 36 #include FT_SIZES_H |
36 #include FT_TRUETYPE_TABLES_H | 37 #include FT_TRUETYPE_TABLES_H |
37 #include FT_TYPE1_TABLES_H | 38 #include FT_TYPE1_TABLES_H |
38 #include FT_BITMAP_H | 39 #include FT_BITMAP_H |
39 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. | 40 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. |
40 #include FT_SYNTHESIS_H | 41 #include FT_SYNTHESIS_H |
41 #include FT_XFREE86_H | 42 #include FT_XFREE86_H |
42 #ifdef FT_LCD_FILTER_H | 43 #ifdef FT_LCD_FILTER_H |
43 #include FT_LCD_FILTER_H | 44 #include FT_LCD_FILTER_H |
44 #endif | 45 #endif |
45 | 46 |
| 47 // Defined in FreeType 2.3.8 and later. |
| 48 // This is a silly build time check, we would need a runtime check if we really
cared. |
46 #ifdef FT_ADVANCES_H | 49 #ifdef FT_ADVANCES_H |
47 #include FT_ADVANCES_H | 50 #include FT_ADVANCES_H |
48 #endif | 51 #endif |
49 | 52 |
50 #if 0 | 53 #if 0 |
51 // Also include the files by name for build tools which require this. | 54 // Also include the files by name for build tools which require this. |
52 #include <freetype/freetype.h> | 55 #include <freetype/freetype.h> |
53 #include <freetype/ftoutln.h> | 56 #include <freetype/ftoutln.h> |
54 #include <freetype/ftsizes.h> | 57 #include <freetype/ftsizes.h> |
55 #include <freetype/tttables.h> | 58 #include <freetype/tttables.h> |
(...skipping 630 matching lines...) Loading... |
686 | 689 |
687 if (!canEmbed(face)) | 690 if (!canEmbed(face)) |
688 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; | 691 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; |
689 | 692 |
690 return info; | 693 return info; |
691 #endif | 694 #endif |
692 } | 695 } |
693 | 696 |
694 /////////////////////////////////////////////////////////////////////////// | 697 /////////////////////////////////////////////////////////////////////////// |
695 | 698 |
696 #define BLACK_LUMINANCE_LIMIT 0x40 | |
697 #define WHITE_LUMINANCE_LIMIT 0xA0 | |
698 | |
699 static bool bothZero(SkScalar a, SkScalar b) { | 699 static bool bothZero(SkScalar a, SkScalar b) { |
700 return 0 == a && 0 == b; | 700 return 0 == a && 0 == b; |
701 } | 701 } |
702 | 702 |
703 // returns false if there is any non-90-rotation or skew | 703 // returns false if there is any non-90-rotation or skew |
704 static bool isAxisAligned(const SkScalerContext::Rec& rec) { | 704 static bool isAxisAligned(const SkScalerContext::Rec& rec) { |
705 return 0 == rec.fPreSkewX && | 705 return 0 == rec.fPreSkewX && |
706 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || | 706 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || |
707 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); | 707 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); |
708 } | 708 } |
(...skipping 133 matching lines...) Loading... |
842 // load the font file | 842 // load the font file |
843 fStrikeIndex = -1; | 843 fStrikeIndex = -1; |
844 fFTSize = NULL; | 844 fFTSize = NULL; |
845 fFace = NULL; | 845 fFace = NULL; |
846 fFaceRec = ref_ft_face(typeface); | 846 fFaceRec = ref_ft_face(typeface); |
847 if (NULL == fFaceRec) { | 847 if (NULL == fFaceRec) { |
848 return; | 848 return; |
849 } | 849 } |
850 fFace = fFaceRec->fFace; | 850 fFace = fFaceRec->fFace; |
851 | 851 |
852 // compute our factors from the record | 852 // A is the total matrix. |
| 853 SkMatrix A; |
| 854 fRec.getSingleMatrix(&A); |
853 | 855 |
854 SkMatrix m; | 856 SkScalar sx = A.getScaleX(); |
855 | 857 SkScalar sy = A.getScaleY(); |
856 fRec.getSingleMatrix(&m); | |
857 | |
858 #ifdef DUMP_STRIKE_CREATION | |
859 SkString keyString; | |
860 SkFontHost::GetDescriptorKeyString(desc, &keyString); | |
861 printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n",
SkScalarToFloat(fRec.fTextSize), | |
862 SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX), | |
863 SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0
][1]), | |
864 SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1
][1]), | |
865 fRec.getHinting(), fRec.fMaskFormat, keyString.c_str()); | |
866 #endif | |
867 | |
868 // now compute our scale factors | |
869 SkScalar sx = m.getScaleX(); | |
870 SkScalar sy = m.getScaleY(); | |
871 | |
872 fMatrix22Scalar.reset(); | 858 fMatrix22Scalar.reset(); |
873 | 859 |
874 if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) { | 860 // In GDI, the hinter is aware of the current transformation |
875 // sort of give up on hinting | 861 // (the transform is in some sense applied before/with the hinting). |
876 sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX())); | 862 // The bytecode can then test if it is rotated or stretched and decide |
877 sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy)); | 863 // to apply instructions or not. |
878 sx = sy = SkScalarAve(sx, sy); | 864 // |
| 865 // FreeType, however, always does the transformation strictly after hinting. |
| 866 // It just sets 'rotated' and 'stretched' to false and only applies the |
| 867 // size before hinting. |
| 868 // |
| 869 // Also, FreeType respects the head::flags::IntegerScaling flag, |
| 870 // (although this is patched out on most major distros) |
| 871 // so it is critical to get the size correct on the request. |
| 872 // |
| 873 // This also gets us the actual closest size on bitmap fonts as well. |
| 874 if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) { |
| 875 // h is where A maps the horizontal baseline. |
| 876 SkPoint h = SkPoint::Make(SK_Scalar1, 0); |
| 877 A.mapPoints(&h, 1); |
879 | 878 |
880 SkScalar inv = SkScalarInvert(sx); | 879 // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). |
| 880 SkMatrix G; |
| 881 Sk2x2Givens(h, &G); |
881 | 882 |
882 // flip the skew elements to go from our Y-down system to FreeType's | 883 // GA is the matrix A with rotation removed. |
883 fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv)); | 884 SkMatrix GA(G); |
884 fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv)); | 885 GA.preConcat(A); |
885 fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv)); | |
886 fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv)); | |
887 | 886 |
888 fMatrix22Scalar.setScaleX(SkScalarMul(m.getScaleX(), inv)); | 887 sx = SkScalarAbs(GA.get(SkMatrix::kMScaleX)); |
889 fMatrix22Scalar.setSkewX(-SkScalarMul(m.getSkewX(), inv)); | 888 sy = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); |
890 fMatrix22Scalar.setSkewY(-SkScalarMul(m.getSkewY(), inv)); | 889 |
891 fMatrix22Scalar.setScaleY(SkScalarMul(m.getScaleY(), inv)); | 890 // sA is the total matrix A without the text scale. |
892 } else { | 891 SkMatrix sA(A); |
893 fMatrix22.xx = fMatrix22.yy = SK_Fixed1; | 892 sA.preScale(SkScalarInvert(sx), SkScalarInvert(sy)); //remove text size |
894 fMatrix22.xy = fMatrix22.yx = 0; | 893 |
| 894 fMatrix22Scalar.setScaleX(sA.getScaleX()); |
| 895 fMatrix22Scalar.setSkewX(-sA.getSkewX()); |
| 896 fMatrix22Scalar.setSkewY(-sA.getSkewY()); |
| 897 fMatrix22Scalar.setScaleY(sA.getScaleY()); |
895 } | 898 } |
896 fScale.set(sx, sy); | 899 fScale.set(sx, sy); |
897 fScaleX = SkScalarToFixed(sx); | 900 fScaleX = SkScalarToFixed(sx); |
898 fScaleY = SkScalarToFixed(sy); | 901 fScaleY = SkScalarToFixed(sy); |
| 902 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); |
| 903 fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX()); |
| 904 fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY()); |
| 905 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); |
899 | 906 |
900 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); | 907 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); |
901 | 908 |
902 // compute the flags we send to Load_Glyph | 909 // compute the flags we send to Load_Glyph |
903 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositi
oning_Flag); | 910 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositi
oning_Flag); |
904 { | 911 { |
905 FT_Int32 loadFlags = FT_LOAD_DEFAULT; | 912 FT_Int32 loadFlags = FT_LOAD_DEFAULT; |
906 | 913 |
907 if (SkMask::kBW_Format == fRec.fMaskFormat) { | 914 if (SkMask::kBW_Format == fRec.fMaskFormat) { |
908 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 | 915 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 |
(...skipping 801 matching lines...) Loading... |
1710 *style = (SkTypeface::Style) tempStyle; | 1717 *style = (SkTypeface::Style) tempStyle; |
1711 } | 1718 } |
1712 if (isFixedPitch) { | 1719 if (isFixedPitch) { |
1713 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1720 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
1714 } | 1721 } |
1715 | 1722 |
1716 FT_Done_Face(face); | 1723 FT_Done_Face(face); |
1717 FT_Done_FreeType(library); | 1724 FT_Done_FreeType(library); |
1718 return true; | 1725 return true; |
1719 } | 1726 } |
OLD | NEW |