Chromium Code Reviews

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

Issue 213153006: Fix size of rotated text with FreeType. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | 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 "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...)
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...)
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...)
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 }
OLDNEW

Powered by Google App Engine