| 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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 |