Chromium Code Reviews| 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 |