OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkAdvancedTypefaceMetrics.h" | 8 #include "SkAdvancedTypefaceMetrics.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
12 #include "SkDescriptor.h" | 12 #include "SkDescriptor.h" |
13 #include "SkFDot6.h" | 13 #include "SkFDot6.h" |
14 #include "SkFontDescriptor.h" | 14 #include "SkFontDescriptor.h" |
15 #include "SkFontHost_FreeType_common.h" | 15 #include "SkFontHost_FreeType_common.h" |
16 #include "SkGlyph.h" | 16 #include "SkGlyph.h" |
17 #include "SkMask.h" | 17 #include "SkMask.h" |
18 #include "SkMaskGamma.h" | 18 #include "SkMaskGamma.h" |
19 #include "SkMatrix22.h" | 19 #include "SkMatrix22.h" |
20 #include "SkMutex.h" | 20 #include "SkMutex.h" |
21 #include "SkOTUtils.h" | 21 #include "SkOTUtils.h" |
22 #include "SkPath.h" | 22 #include "SkPath.h" |
23 #include "SkScalerContext.h" | 23 #include "SkScalerContext.h" |
24 #include "SkStream.h" | 24 #include "SkStream.h" |
25 #include "SkString.h" | 25 #include "SkString.h" |
26 #include "SkTemplates.h" | 26 #include "SkTemplates.h" |
27 #include "SkTypes.h" | 27 #include "SkTypes.h" |
28 #include "SkUniquePtr.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_ADVANCES_H | 34 #include FT_ADVANCES_H |
34 #include FT_BITMAP_H | 35 #include FT_BITMAP_H |
35 #include FT_FREETYPE_H | 36 #include FT_FREETYPE_H |
36 #include FT_LCD_FILTER_H | 37 #include FT_LCD_FILTER_H |
37 #include FT_MODULE_H | 38 #include FT_MODULE_H |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 // Android >= Gingerbread (good) | 142 // Android >= Gingerbread (good) |
142 typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char*); | 143 typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char*); |
143 }; | 144 }; |
144 | 145 |
145 struct SkFaceRec; | 146 struct SkFaceRec; |
146 | 147 |
147 SK_DECLARE_STATIC_MUTEX(gFTMutex); | 148 SK_DECLARE_STATIC_MUTEX(gFTMutex); |
148 static FreeTypeLibrary* gFTLibrary; | 149 static FreeTypeLibrary* gFTLibrary; |
149 static SkFaceRec* gFaceRecHead; | 150 static SkFaceRec* gFaceRecHead; |
150 | 151 |
151 // Private to RefFreeType and UnrefFreeType | 152 // Private to ref_ft_library and unref_ft_library |
152 static int gFTCount; | 153 static int gFTCount; |
153 | 154 |
154 // Caller must lock gFTMutex before calling this function. | 155 // Caller must lock gFTMutex before calling this function. |
155 static bool ref_ft_library() { | 156 static bool ref_ft_library() { |
156 gFTMutex.assertHeld(); | 157 gFTMutex.assertHeld(); |
157 SkASSERT(gFTCount >= 0); | 158 SkASSERT(gFTCount >= 0); |
158 | 159 |
159 if (0 == gFTCount) { | 160 if (0 == gFTCount) { |
160 SkASSERT(nullptr == gFTLibrary); | 161 SkASSERT(nullptr == gFTLibrary); |
161 gFTLibrary = new FreeTypeLibrary; | 162 gFTLibrary = new FreeTypeLibrary; |
162 } | 163 } |
163 ++gFTCount; | 164 ++gFTCount; |
164 return gFTLibrary->library(); | 165 return gFTLibrary->library(); |
165 } | 166 } |
166 | 167 |
167 // Caller must lock gFTMutex before calling this function. | 168 // Caller must lock gFTMutex before calling this function. |
168 static void unref_ft_library() { | 169 static void unref_ft_library() { |
169 gFTMutex.assertHeld(); | 170 gFTMutex.assertHeld(); |
170 SkASSERT(gFTCount > 0); | 171 SkASSERT(gFTCount > 0); |
171 | 172 |
172 --gFTCount; | 173 --gFTCount; |
173 if (0 == gFTCount) { | 174 if (0 == gFTCount) { |
175 SkASSERT(nullptr == gFaceRecHead); | |
bungeman-skia
2016/03/01 22:28:06
Adding this assert would have helped find this a b
| |
174 SkASSERT(nullptr != gFTLibrary); | 176 SkASSERT(nullptr != gFTLibrary); |
175 delete gFTLibrary; | 177 delete gFTLibrary; |
176 SkDEBUGCODE(gFTLibrary = nullptr;) | 178 SkDEBUGCODE(gFTLibrary = nullptr;) |
177 } | 179 } |
178 } | 180 } |
179 | 181 |
180 class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { | 182 class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { |
181 public: | 183 public: |
182 SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc); | 184 SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc); |
183 virtual ~SkScalerContext_FreeType(); | 185 virtual ~SkScalerContext_FreeType(); |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
668 delete c; | 670 delete c; |
669 c = nullptr; | 671 c = nullptr; |
670 } | 672 } |
671 return c; | 673 return c; |
672 } | 674 } |
673 | 675 |
674 void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { | 676 void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { |
675 //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 | 677 //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 |
676 //Cap the requested size as larger sizes give bogus values. | 678 //Cap the requested size as larger sizes give bogus values. |
677 //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. | 679 //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. |
680 //Note that this also currently only protects against large text size reques ts, | |
681 //the total matrix is not taken into account here. | |
bungeman-skia
2016/03/01 22:28:06
All of the 'onFilterRec' implementations should be
| |
678 if (rec->fTextSize > SkIntToScalar(1 << 14)) { | 682 if (rec->fTextSize > SkIntToScalar(1 << 14)) { |
679 rec->fTextSize = SkIntToScalar(1 << 14); | 683 rec->fTextSize = SkIntToScalar(1 << 14); |
680 } | 684 } |
681 | 685 |
682 if (isLCD(*rec)) { | 686 if (isLCD(*rec)) { |
683 // TODO: re-work so that FreeType is set-up and selected by the SkFontMg r. | 687 // TODO: re-work so that FreeType is set-up and selected by the SkFontMg r. |
684 SkAutoMutexAcquire ama(gFTMutex); | 688 SkAutoMutexAcquire ama(gFTMutex); |
685 ref_ft_library(); | 689 ref_ft_library(); |
686 if (!gFTLibrary->isLCDSupported()) { | 690 if (!gFTLibrary->isLCDSupported()) { |
687 // If the runtime Freetype library doesn't support LCD, disable it h ere. | 691 // If the runtime Freetype library doesn't support LCD, disable it h ere. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
779 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_nam e, | 783 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_nam e, |
780 chosenStrikeIndex, err)); | 784 chosenStrikeIndex, err)); |
781 chosenStrikeIndex = -1; | 785 chosenStrikeIndex = -1; |
782 } | 786 } |
783 } | 787 } |
784 return chosenStrikeIndex; | 788 return chosenStrikeIndex; |
785 } | 789 } |
786 | 790 |
787 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, const S kDescriptor* desc) | 791 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, const S kDescriptor* desc) |
788 : SkScalerContext_FreeType_Base(typeface, desc) | 792 : SkScalerContext_FreeType_Base(typeface, desc) |
793 , fFace(nullptr) | |
794 , fFTSize(nullptr) | |
795 , fStrikeIndex(-1) | |
789 { | 796 { |
790 SkAutoMutexAcquire ac(gFTMutex); | 797 SkAutoMutexAcquire ac(gFTMutex); |
791 | 798 |
792 if (!ref_ft_library()) { | 799 if (!ref_ft_library()) { |
793 sk_throw(); | 800 sk_throw(); |
794 } | 801 } |
795 | 802 |
796 // load the font file | 803 // load the font file |
797 fStrikeIndex = -1; | 804 using UnrefFTFace = SkFunctionWrapper<void, skstd::remove_pointer_t<FT_Face> , unref_ft_face>; |
798 fFTSize = nullptr; | 805 skstd::unique_ptr<skstd::remove_pointer_t<FT_Face>, UnrefFTFace> ftFace(ref_ ft_face(typeface)); |
799 fFace = ref_ft_face(typeface); | 806 if (nullptr == ftFace) { |
800 if (nullptr == fFace) { | 807 SkDEBUGF(("Could not create FT_Face.\n")); |
801 return; | 808 return; |
802 } | 809 } |
803 | 810 |
804 fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMa trix22Scalar); | 811 fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMa trix22Scalar); |
805 fMatrix22Scalar.setSkewX(-fMatrix22Scalar.getSkewX()); | 812 fMatrix22Scalar.setSkewX(-fMatrix22Scalar.getSkewX()); |
806 fMatrix22Scalar.setSkewY(-fMatrix22Scalar.getSkewY()); | 813 fMatrix22Scalar.setSkewY(-fMatrix22Scalar.getSkewY()); |
807 | 814 |
808 fScaleX = SkScalarToFDot6(fScale.fX); | 815 fScaleX = SkScalarToFDot6(fScale.fX); |
809 fScaleY = SkScalarToFDot6(fScale.fY); | 816 fScaleY = SkScalarToFDot6(fScale.fY); |
810 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); | 817 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
876 // Use vertical layout if requested. | 883 // Use vertical layout if requested. |
877 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 884 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
878 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; | 885 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; |
879 } | 886 } |
880 | 887 |
881 loadFlags |= FT_LOAD_COLOR; | 888 loadFlags |= FT_LOAD_COLOR; |
882 | 889 |
883 fLoadGlyphFlags = loadFlags; | 890 fLoadGlyphFlags = loadFlags; |
884 } | 891 } |
885 | 892 |
886 FT_Error err = FT_New_Size(fFace, &fFTSize); | 893 using DoneFTSize = SkFunctionWrapper<FT_Error, skstd::remove_pointer_t<FT_Si ze>, FT_Done_Size>; |
887 if (err != 0) { | 894 skstd::unique_ptr<skstd::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([&ftF ace]() -> FT_Size { |
888 SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, fFace->family_na me)); | 895 FT_Size size; |
889 fFace = nullptr; | 896 FT_Error err = FT_New_Size(ftFace.get(), &size); |
890 return; | 897 if (err != 0) { |
891 } | 898 SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, ftFace->fami ly_name)); |
892 err = FT_Activate_Size(fFTSize); | 899 return nullptr; |
893 if (err != 0) { | 900 } |
894 SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", fFace, f ScaleX, fScaleY, | 901 return size; |
dogben
2016/03/02 00:55:22
ignorable nit: Seems like it would be simpler to d
| |
895 err)); | 902 }()); |
896 fFTSize = nullptr; | 903 if (nullptr == ftSize) { |
904 SkDEBUGF(("Could not create FT_Size.\n")); | |
897 return; | 905 return; |
898 } | 906 } |
899 | 907 |
900 if (FT_IS_SCALABLE(fFace)) { | 908 FT_Error err = FT_Activate_Size(ftSize.get()); |
901 err = FT_Set_Char_Size(fFace, fScaleX, fScaleY, 72, 72); | 909 if (err != 0) { |
910 SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", | |
911 ftFace.get(), fScaleX, fScaleY, err)); | |
912 return; | |
913 } | |
914 | |
915 if (FT_IS_SCALABLE(ftFace)) { | |
916 err = FT_Set_Char_Size(ftFace.get(), fScaleX, fScaleY, 72, 72); | |
902 if (err != 0) { | 917 if (err != 0) { |
903 SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n", | 918 SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n", |
904 fFace, fScaleX, fScaleY, err)); | 919 ftFace.get(), fScaleX, fScaleY, err)); |
905 fFace = nullptr; | |
bungeman-skia
2016/03/01 22:28:06
The related bug was because we went down this path
| |
906 return; | 920 return; |
907 } | 921 } |
908 FT_Set_Transform(fFace, &fMatrix22, nullptr); | 922 FT_Set_Transform(ftFace.get(), &fMatrix22, nullptr); |
909 } else if (FT_HAS_FIXED_SIZES(fFace)) { | 923 } else if (FT_HAS_FIXED_SIZES(ftFace)) { |
910 fStrikeIndex = chooseBitmapStrike(fFace, fScaleY); | 924 fStrikeIndex = chooseBitmapStrike(ftFace.get(), fScaleY); |
911 if (fStrikeIndex == -1) { | 925 if (fStrikeIndex == -1) { |
912 SkDEBUGF(("no glyphs for font \"%s\" size %f?\n", | 926 SkDEBUGF(("no glyphs for font \"%s\" size %f?\n", |
913 fFace->family_name, SkFDot6ToScalar(fScaleY))) ; | 927 ftFace->family_name, SkFDot6ToScalar(fScaleY))) ; |
914 } else { | 928 } else { |
915 // FreeType does no provide linear metrics for bitmap fonts. | 929 // FreeType does no provide linear metrics for bitmap fonts. |
916 linearMetrics = false; | 930 linearMetrics = false; |
917 | 931 |
918 // FreeType documentation says: | 932 // FreeType documentation says: |
919 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. | 933 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. |
920 // Bitmap-only fonts ignore this flag. | 934 // Bitmap-only fonts ignore this flag. |
921 // | 935 // |
922 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. | 936 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. |
923 // Force this flag off for bitmap only fonts. | 937 // Force this flag off for bitmap only fonts. |
924 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP; | 938 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP; |
925 } | 939 } |
926 } else { | 940 } else { |
927 SkDEBUGF(("unknown kind of font \"%s\" size %f?\n", | 941 SkDEBUGF(("unknown kind of font \"%s\" size %f?\n", |
928 fFace->family_name, SkFDot6ToScalar(fScaleY))); | 942 fFace->family_name, SkFDot6ToScalar(fScaleY))); |
929 } | 943 } |
930 | 944 |
945 fFTSize = ftSize.release(); | |
946 fFace = ftFace.release(); | |
931 fDoLinearMetrics = linearMetrics; | 947 fDoLinearMetrics = linearMetrics; |
932 } | 948 } |
933 | 949 |
934 SkScalerContext_FreeType::~SkScalerContext_FreeType() { | 950 SkScalerContext_FreeType::~SkScalerContext_FreeType() { |
935 SkAutoMutexAcquire ac(gFTMutex); | 951 SkAutoMutexAcquire ac(gFTMutex); |
936 | 952 |
937 if (fFTSize != nullptr) { | 953 if (fFTSize != nullptr) { |
938 FT_Done_Size(fFTSize); | 954 FT_Done_Size(fFTSize); |
939 } | 955 } |
940 | 956 |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1790 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", | 1806 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", |
1791 name.c_str(), | 1807 name.c_str(), |
1792 (skTag >> 24) & 0xFF, | 1808 (skTag >> 24) & 0xFF, |
1793 (skTag >> 16) & 0xFF, | 1809 (skTag >> 16) & 0xFF, |
1794 (skTag >> 8) & 0xFF, | 1810 (skTag >> 8) & 0xFF, |
1795 (skTag) & 0xFF)); | 1811 (skTag) & 0xFF)); |
1796 } | 1812 } |
1797 } | 1813 } |
1798 ) | 1814 ) |
1799 } | 1815 } |
OLD | NEW |