Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

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

Issue 2139703002: Rotate emoji with FreeType. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Modify subpixel condition. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/ports/SkFontHost_FreeType_common.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 unsigned generateGlyphCount() override; 190 unsigned generateGlyphCount() override;
191 uint16_t generateCharToGlyph(SkUnichar uni) override; 191 uint16_t generateCharToGlyph(SkUnichar uni) override;
192 void generateAdvance(SkGlyph* glyph) override; 192 void generateAdvance(SkGlyph* glyph) override;
193 void generateMetrics(SkGlyph* glyph) override; 193 void generateMetrics(SkGlyph* glyph) override;
194 void generateImage(const SkGlyph& glyph) override; 194 void generateImage(const SkGlyph& glyph) override;
195 void generatePath(const SkGlyph& glyph, SkPath* path) override; 195 void generatePath(const SkGlyph& glyph, SkPath* path) override;
196 void generateFontMetrics(SkPaint::FontMetrics*) override; 196 void generateFontMetrics(SkPaint::FontMetrics*) override;
197 SkUnichar generateGlyphToChar(uint16_t glyph) override; 197 SkUnichar generateGlyphToChar(uint16_t glyph) override;
198 198
199 private: 199 private:
200 FT_Face fFace; // reference to shared face in gFaceRecHead 200 FT_Face fFace; // Shared face from gFaceRecHead.
201 FT_Size fFTSize; // our own copy 201 FT_Size fFTSize; // The size on the fFace for this scaler.
202 FT_Int fStrikeIndex; 202 FT_Int fStrikeIndex;
203 FT_F26Dot6 fScaleX, fScaleY;
204 FT_Matrix fMatrix22;
205 uint32_t fLoadGlyphFlags;
206 bool fDoLinearMetrics;
207 bool fLCDIsVert;
208 203
209 // Need scalar versions for generateFontMetrics 204 /** The rest of the matrix after FreeType handles the size.
210 SkVector fScale; 205 * With outline font rasterization this is handled by FreeType with FT_Set_ Transform.
211 SkMatrix fMatrix22Scalar; 206 * With bitmap only fonts this matrix must be applied to scale the bitmap.
207 */
208 SkMatrix fMatrix22Scalar;
209 /** Same as fMatrix22Scalar, but in FreeType units and space. */
210 FT_Matrix fMatrix22;
211 /** The actual size requested. */
212 SkVector fScale;
213
214 uint32_t fLoadGlyphFlags;
215 bool fDoLinearMetrics;
216 bool fLCDIsVert;
212 217
213 FT_Error setupSize(); 218 FT_Error setupSize();
214 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, 219 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox,
215 bool snapToPixelBoundary = false); 220 bool snapToPixelBoundary = false);
216 bool getCBoxForLetter(char letter, FT_BBox* bbox); 221 bool getCBoxForLetter(char letter, FT_BBox* bbox);
217 // Caller must lock gFTMutex before calling this function. 222 // Caller must lock gFTMutex before calling this function.
218 void updateGlyphIfLCD(SkGlyph* glyph); 223 void updateGlyphIfLCD(SkGlyph* glyph);
219 // Caller must lock gFTMutex before calling this function. 224 // Caller must lock gFTMutex before calling this function.
220 // update FreeType2 glyph slot with glyph emboldened 225 // update FreeType2 glyph slot with glyph emboldened
221 void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph); 226 void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph);
227 bool shouldSubpixelBitmap(const SkGlyph&, const SkMatrix&);
222 }; 228 };
223 229
224 /////////////////////////////////////////////////////////////////////////// 230 ///////////////////////////////////////////////////////////////////////////
225 /////////////////////////////////////////////////////////////////////////// 231 ///////////////////////////////////////////////////////////////////////////
226 232
227 struct SkFaceRec { 233 struct SkFaceRec {
228 SkFaceRec* fNext; 234 SkFaceRec* fNext;
229 FT_Face fFace; 235 FT_Face fFace;
230 FT_StreamRec fFTStream; 236 FT_StreamRec fFTStream;
231 SkAutoTDelete<SkStreamAsset> fSkStream; 237 SkAutoTDelete<SkStreamAsset> fSkStream;
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], 746 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1],
741 FT_KERNING_UNSCALED, &delta); 747 FT_KERNING_UNSCALED, &delta);
742 if (err) { 748 if (err) {
743 return false; 749 return false;
744 } 750 }
745 adjustments[i] = delta.x; 751 adjustments[i] = delta.x;
746 } 752 }
747 return true; 753 return true;
748 } 754 }
749 755
756 /** Returns the bitmap strike equal to or just larger than the requested size. * /
750 static FT_Int chooseBitmapStrike(FT_Face face, FT_F26Dot6 scaleY) { 757 static FT_Int chooseBitmapStrike(FT_Face face, FT_F26Dot6 scaleY) {
751 // early out if face is bad
752 if (face == nullptr) { 758 if (face == nullptr) {
753 SkDEBUGF(("chooseBitmapStrike aborted due to nullptr face\n")); 759 SkDEBUGF(("chooseBitmapStrike aborted due to nullptr face.\n"));
754 return -1; 760 return -1;
755 } 761 }
756 // determine target ppem 762
757 FT_Pos targetPPEM = scaleY; 763 FT_Pos requestedPPEM = scaleY; // FT_Bitmap_Size::y_ppem is in 26.6 format.
758 // find a bitmap strike equal to or just larger than the requested size
759 FT_Int chosenStrikeIndex = -1; 764 FT_Int chosenStrikeIndex = -1;
760 FT_Pos chosenPPEM = 0; 765 FT_Pos chosenPPEM = 0;
761 for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIn dex) { 766 for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIn dex) {
762 FT_Pos thisPPEM = face->available_sizes[strikeIndex].y_ppem; 767 FT_Pos strikePPEM = face->available_sizes[strikeIndex].y_ppem;
763 if (thisPPEM == targetPPEM) { 768 if (strikePPEM == requestedPPEM) {
764 // exact match - our search stops here 769 // exact match - our search stops here
765 chosenPPEM = thisPPEM; 770 return strikeIndex;
766 chosenStrikeIndex = strikeIndex; 771 } else if (chosenPPEM < requestedPPEM) {
767 break;
768 } else if (chosenPPEM < targetPPEM) {
769 // attempt to increase chosenPPEM 772 // attempt to increase chosenPPEM
770 if (thisPPEM > chosenPPEM) { 773 if (chosenPPEM < strikePPEM) {
771 chosenPPEM = thisPPEM; 774 chosenPPEM = strikePPEM;
772 chosenStrikeIndex = strikeIndex; 775 chosenStrikeIndex = strikeIndex;
773 } 776 }
774 } else { 777 } else {
775 // attempt to decrease chosenPPEM, but not below targetPPEM 778 // attempt to decrease chosenPPEM, but not below requestedPPEM
776 if (thisPPEM < chosenPPEM && thisPPEM > targetPPEM) { 779 if (requestedPPEM < strikePPEM && strikePPEM < chosenPPEM) {
777 chosenPPEM = thisPPEM; 780 chosenPPEM = strikePPEM;
778 chosenStrikeIndex = strikeIndex; 781 chosenStrikeIndex = strikeIndex;
779 } 782 }
780 } 783 }
781 } 784 }
782 if (chosenStrikeIndex != -1) {
783 // use the chosen strike
784 FT_Error err = FT_Select_Size(face, chosenStrikeIndex);
785 if (err != 0) {
786 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_nam e,
787 chosenStrikeIndex, err));
788 chosenStrikeIndex = -1;
789 }
790 }
791 return chosenStrikeIndex; 785 return chosenStrikeIndex;
792 } 786 }
793 787
794 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, 788 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
795 const SkScalerContextEffects& effects, 789 const SkScalerContextEffects& effects,
796 const SkDescriptor* desc) 790 const SkDescriptor* desc)
797 : SkScalerContext_FreeType_Base(typeface, effects, desc) 791 : SkScalerContext_FreeType_Base(typeface, effects, desc)
798 , fFace(nullptr) 792 , fFace(nullptr)
799 , fFTSize(nullptr) 793 , fFTSize(nullptr)
800 , fStrikeIndex(-1) 794 , fStrikeIndex(-1)
801 { 795 {
802 SkAutoMutexAcquire ac(gFTMutex); 796 SkAutoMutexAcquire ac(gFTMutex);
803 797
804 if (!ref_ft_library()) { 798 if (!ref_ft_library()) {
805 sk_throw(); 799 sk_throw();
806 } 800 }
807 801
808 // load the font file 802 // load the font file
809 using UnrefFTFace = SkFunctionWrapper<void, skstd::remove_pointer_t<FT_Face> , unref_ft_face>; 803 using UnrefFTFace = SkFunctionWrapper<void, skstd::remove_pointer_t<FT_Face> , unref_ft_face>;
810 std::unique_ptr<skstd::remove_pointer_t<FT_Face>, UnrefFTFace> ftFace(ref_ft _face(typeface)); 804 std::unique_ptr<skstd::remove_pointer_t<FT_Face>, UnrefFTFace> ftFace(ref_ft _face(typeface));
811 if (nullptr == ftFace) { 805 if (nullptr == ftFace) {
812 SkDEBUGF(("Could not create FT_Face.\n")); 806 SkDEBUGF(("Could not create FT_Face.\n"));
813 return; 807 return;
814 } 808 }
815 809
816 fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMa trix22Scalar); 810 fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMa trix22Scalar);
817 fMatrix22Scalar.setSkewX(-fMatrix22Scalar.getSkewX());
818 fMatrix22Scalar.setSkewY(-fMatrix22Scalar.getSkewY());
819 811
820 fScaleX = SkScalarToFDot6(fScale.fX); 812 FT_F26Dot6 scaleX = SkScalarToFDot6(fScale.fX);
821 fScaleY = SkScalarToFDot6(fScale.fY); 813 FT_F26Dot6 scaleY = SkScalarToFDot6(fScale.fY);
822 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 814 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX());
823 fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX()); 815 fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX());
824 fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY()); 816 fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY());
825 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 817 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY());
826 818
827 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 819 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
828 820
829 // compute the flags we send to Load_Glyph 821 // compute the flags we send to Load_Glyph
830 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositi oning_Flag); 822 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositi oning_Flag);
831 { 823 {
832 FT_Int32 loadFlags = FT_LOAD_DEFAULT; 824 FT_Int32 loadFlags = FT_LOAD_DEFAULT;
833 825
834 if (SkMask::kBW_Format == fRec.fMaskFormat) { 826 if (SkMask::kBW_Format == fRec.fMaskFormat) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 loadFlags |= FT_LOAD_COLOR; 885 loadFlags |= FT_LOAD_COLOR;
894 886
895 fLoadGlyphFlags = loadFlags; 887 fLoadGlyphFlags = loadFlags;
896 } 888 }
897 889
898 using DoneFTSize = SkFunctionWrapper<FT_Error, skstd::remove_pointer_t<FT_Si ze>, FT_Done_Size>; 890 using DoneFTSize = SkFunctionWrapper<FT_Error, skstd::remove_pointer_t<FT_Si ze>, FT_Done_Size>;
899 std::unique_ptr<skstd::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([&ftFac e]() -> FT_Size { 891 std::unique_ptr<skstd::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([&ftFac e]() -> FT_Size {
900 FT_Size size; 892 FT_Size size;
901 FT_Error err = FT_New_Size(ftFace.get(), &size); 893 FT_Error err = FT_New_Size(ftFace.get(), &size);
902 if (err != 0) { 894 if (err != 0) {
903 SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, ftFace->fami ly_name)); 895 SkDEBUGF(("FT_New_Size(%s) returned 0x%x.\n", ftFace->family_name, e rr));
904 return nullptr; 896 return nullptr;
905 } 897 }
906 return size; 898 return size;
907 }()); 899 }());
908 if (nullptr == ftSize) { 900 if (nullptr == ftSize) {
909 SkDEBUGF(("Could not create FT_Size.\n")); 901 SkDEBUGF(("Could not create FT_Size.\n"));
910 return; 902 return;
911 } 903 }
912 904
913 FT_Error err = FT_Activate_Size(ftSize.get()); 905 FT_Error err = FT_Activate_Size(ftSize.get());
914 if (err != 0) { 906 if (err != 0) {
915 SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", 907 SkDEBUGF(("FT_Activate_Size(%s) returned 0x%x.\n", ftFace->family_name, err));
916 ftFace.get(), fScaleX, fScaleY, err));
917 return; 908 return;
918 } 909 }
919 910
920 if (FT_IS_SCALABLE(ftFace)) { 911 if (FT_IS_SCALABLE(ftFace)) {
921 err = FT_Set_Char_Size(ftFace.get(), fScaleX, fScaleY, 72, 72); 912 err = FT_Set_Char_Size(ftFace.get(), scaleX, scaleY, 72, 72);
922 if (err != 0) { 913 if (err != 0) {
923 SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n", 914 SkDEBUGF(("FT_Set_CharSize(%s, %f, %f) returned 0x%x.\n",
924 ftFace.get(), fScaleX, fScaleY, err)); 915 ftFace->family_name, fScale.fX, fScale.fY, err));
925 return; 916 return;
926 } 917 }
927 FT_Set_Transform(ftFace.get(), &fMatrix22, nullptr);
928 } else if (FT_HAS_FIXED_SIZES(ftFace)) { 918 } else if (FT_HAS_FIXED_SIZES(ftFace)) {
929 fStrikeIndex = chooseBitmapStrike(ftFace.get(), fScaleY); 919 fStrikeIndex = chooseBitmapStrike(ftFace.get(), scaleY);
930 if (fStrikeIndex == -1) { 920 if (fStrikeIndex == -1) {
931 SkDEBUGF(("no glyphs for font \"%s\" size %f?\n", 921 SkDEBUGF(("No glyphs for font \"%s\" size %f.\n", ftFace->family_nam e, fScale.fY));
932 ftFace->family_name, SkFDot6ToScalar(fScaleY))) ; 922 return;
933 } else { 923 }
934 // FreeType does no provide linear metrics for bitmap fonts.
935 linearMetrics = false;
936 924
937 // FreeType documentation says: 925 err = FT_Select_Size(ftFace.get(), fStrikeIndex);
938 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. 926 if (err != 0) {
939 // Bitmap-only fonts ignore this flag. 927 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x.\n",
940 // 928 ftFace->family_name, fStrikeIndex, err));
941 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. 929 fStrikeIndex = -1;
942 // Force this flag off for bitmap only fonts. 930 return;
943 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP;
944 } 931 }
932
933 // A non-ideal size was picked, so recompute the matrix.
934 // This adjusts for the difference between FT_Set_Char_Size and FT_Selec t_Size.
935 fMatrix22Scalar.preScale(fScale.x() / ftFace->size->metrics.x_ppem,
936 fScale.y() / ftFace->size->metrics.y_ppem);
937 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX());
938 fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX());
939 fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY());
940 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY());
941
942 // FreeType does not provide linear metrics for bitmap fonts.
943 linearMetrics = false;
944
945 // FreeType documentation says:
946 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading.
947 // Bitmap-only fonts ignore this flag.
948 //
949 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag.
950 // Force this flag off for bitmap only fonts.
951 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP;
945 } else { 952 } else {
946 SkDEBUGF(("unknown kind of font \"%s\" size %f?\n", 953 SkDEBUGF(("Unknown kind of font \"%s\" size %f.\n", fFace->family_name, fScale.fY));
947 fFace->family_name, SkFDot6ToScalar(fScaleY))); 954 return;
948 } 955 }
949 956
950 fFTSize = ftSize.release(); 957 fFTSize = ftSize.release();
951 fFace = ftFace.release(); 958 fFace = ftFace.release();
952 fDoLinearMetrics = linearMetrics; 959 fDoLinearMetrics = linearMetrics;
953 } 960 }
954 961
955 SkScalerContext_FreeType::~SkScalerContext_FreeType() { 962 SkScalerContext_FreeType::~SkScalerContext_FreeType() {
956 SkAutoMutexAcquire ac(gFTMutex); 963 SkAutoMutexAcquire ac(gFTMutex);
957 964
958 if (fFTSize != nullptr) { 965 if (fFTSize != nullptr) {
959 FT_Done_Size(fFTSize); 966 FT_Done_Size(fFTSize);
960 } 967 }
961 968
962 if (fFace != nullptr) { 969 if (fFace != nullptr) {
963 unref_ft_face(fFace); 970 unref_ft_face(fFace);
964 } 971 }
965 972
966 unref_ft_library(); 973 unref_ft_library();
967 } 974 }
968 975
969 /* We call this before each use of the fFace, since we may be sharing 976 /* We call this before each use of the fFace, since we may be sharing
970 this face with other context (at different sizes). 977 this face with other context (at different sizes).
971 */ 978 */
972 FT_Error SkScalerContext_FreeType::setupSize() { 979 FT_Error SkScalerContext_FreeType::setupSize() {
973 gFTMutex.assertHeld(); 980 gFTMutex.assertHeld();
974 FT_Error err = FT_Activate_Size(fFTSize); 981 FT_Error err = FT_Activate_Size(fFTSize);
975 if (err != 0) { 982 if (err != 0) {
976 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%s %s, 0x%x, 0x%x) returned 0x%x\n",
977 fFace->family_name, fFace->style_name, fScaleX, fScaleY, err)) ;
978 fFTSize = nullptr;
979 return err; 983 return err;
980 } 984 }
981
982 // seems we need to reset this every time (not sure why, but without it
983 // I get random italics from some other fFTSize)
984 FT_Set_Transform(fFace, &fMatrix22, nullptr); 985 FT_Set_Transform(fFace, &fMatrix22, nullptr);
985 return 0; 986 return 0;
986 } 987 }
987 988
988 unsigned SkScalerContext_FreeType::generateGlyphCount() { 989 unsigned SkScalerContext_FreeType::generateGlyphCount() {
989 return fFace->num_glyphs; 990 return fFace->num_glyphs;
990 } 991 }
991 992
992 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 993 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) {
993 SkAutoMutexAcquire ac(gFTMutex); 994 SkAutoMutexAcquire ac(gFTMutex);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 FT_Fixed advance; 1031 FT_Fixed advance;
1031 1032
1032 error = FT_Get_Advance( fFace, glyph->getGlyphID(), 1033 error = FT_Get_Advance( fFace, glyph->getGlyphID(),
1033 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 1034 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY,
1034 &advance ); 1035 &advance );
1035 if (0 == error) { 1036 if (0 == error) {
1036 glyph->fRsbDelta = 0; 1037 glyph->fRsbDelta = 0;
1037 glyph->fLsbDelta = 0; 1038 glyph->fLsbDelta = 0;
1038 const SkScalar advanceScalar = SkFT_FixedToScalar(advance); 1039 const SkScalar advanceScalar = SkFT_FixedToScalar(advance);
1039 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * adv anceScalar); 1040 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * adv anceScalar);
1040 glyph->fAdvanceY = -SkScalarToFloat(fMatrix22Scalar.getSkewY() * adv anceScalar); 1041 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * adva nceScalar);
1041 return; 1042 return;
1042 } 1043 }
1043 } 1044 }
1044 1045
1045 /* otherwise, we need to load/hint the glyph, which is slower */ 1046 /* otherwise, we need to load/hint the glyph, which is slower */
1046 this->generateMetrics(glyph); 1047 this->generateMetrics(glyph);
1047 return; 1048 return;
1048 } 1049 }
1049 1050
1050 void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph, 1051 void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 if (fLCDIsVert) { 1105 if (fLCDIsVert) {
1105 glyph->fHeight += gFTLibrary->lcdExtra(); 1106 glyph->fHeight += gFTLibrary->lcdExtra();
1106 glyph->fTop -= gFTLibrary->lcdExtra() >> 1; 1107 glyph->fTop -= gFTLibrary->lcdExtra() >> 1;
1107 } else { 1108 } else {
1108 glyph->fWidth += gFTLibrary->lcdExtra(); 1109 glyph->fWidth += gFTLibrary->lcdExtra();
1109 glyph->fLeft -= gFTLibrary->lcdExtra() >> 1; 1110 glyph->fLeft -= gFTLibrary->lcdExtra() >> 1;
1110 } 1111 }
1111 } 1112 }
1112 } 1113 }
1113 1114
1114 inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) { 1115 bool SkScalerContext_FreeType::shouldSubpixelBitmap(const SkGlyph& glyph, const SkMatrix& matrix) {
1115 glyph.fWidth *= scale; 1116 // Do subpixel on bitmaps if glyph is bitmap and subpixel requested and
1116 glyph.fHeight *= scale; 1117 // (font has no outlines or already transforming bitmap).
mtklein 2016/07/15 21:08:48 might help to explain each of the subtle two heuri
bungeman-skia 2016/07/15 21:30:29 Done.
mtklein 2016/07/15 22:38:17 Thanks! This is awesome.
1117 glyph.fTop *= scale; 1118 return fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP &&
1118 glyph.fLeft *= scale; 1119 fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag &&
1119 1120 (glyph.getSubXFixed() || glyph.getSubYFixed()) &&
1120 float floatScale = SkScalarToFloat(scale); 1121 (!FT_IS_SCALABLE(fFace) || !matrix.isIdentity());
1121 glyph.fAdvanceX *= floatScale;
1122 glyph.fAdvanceY *= floatScale;
1123 } 1122 }
1124 1123
1125 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 1124 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
1126 SkAutoMutexAcquire ac(gFTMutex); 1125 SkAutoMutexAcquire ac(gFTMutex);
1127 1126
1128 glyph->fRsbDelta = 0; 1127 glyph->fRsbDelta = 0;
1129 glyph->fLsbDelta = 0; 1128 glyph->fLsbDelta = 0;
1130 1129
1131 FT_Error err; 1130 FT_Error err;
1132 1131
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri cs.horiBearingY; 1168 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri cs.horiBearingY;
1170 FT_Vector_Transform(&vector, &fMatrix22); 1169 FT_Vector_Transform(&vector, &fMatrix22);
1171 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); 1170 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
1172 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); 1171 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y);
1173 } 1172 }
1174 1173
1175 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { 1174 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
1176 glyph->fMaskFormat = SkMask::kARGB32_Format; 1175 glyph->fMaskFormat = SkMask::kARGB32_Format;
1177 } 1176 }
1178 1177
1179 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); 1178 {
1180 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); 1179 SkRect rect = SkRect::MakeXYWH(SkIntToScalar(fFace->glyph->bitmap_le ft),
1181 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); 1180 -SkIntToScalar(fFace->glyph->bitmap_to p),
1182 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); 1181 SkIntToScalar(fFace->glyph->bitmap.wi dth),
1182 SkIntToScalar(fFace->glyph->bitmap.ro ws));
1183 fMatrix22Scalar.mapRect(&rect);
1184 if (this->shouldSubpixelBitmap(*glyph, fMatrix22Scalar)) {
1185 rect.offset(SkFixedToScalar(glyph->getSubXFixed()),
1186 SkFixedToScalar(glyph->getSubYFixed()));
1187 }
1188 SkIRect irect = rect.roundOut();
1189 glyph->fWidth = SkToU16(irect.width());
1190 glyph->fHeight = SkToU16(irect.height());
1191 glyph->fTop = SkToS16(irect.top());
1192 glyph->fLeft = SkToS16(irect.left());
1193 }
1183 break; 1194 break;
1184 1195
1185 default: 1196 default:
1186 SkDEBUGFAIL("unknown glyph format"); 1197 SkDEBUGFAIL("unknown glyph format");
1187 glyph->zeroMetrics(); 1198 glyph->zeroMetrics();
1188 return; 1199 return;
1189 } 1200 }
1190 1201
1191 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1202 if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
1192 if (fDoLinearMetrics) { 1203 if (fDoLinearMetrics) {
1193 const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->line arVertAdvance); 1204 const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->line arVertAdvance);
1194 glyph->fAdvanceX = -SkScalarToFloat(fMatrix22Scalar.getSkewX() * adv anceScalar); 1205 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getSkewX() * adva nceScalar);
1195 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * adv anceScalar); 1206 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * adv anceScalar);
1196 } else { 1207 } else {
1197 glyph->fAdvanceX = -SkFDot6ToFloat(fFace->glyph->advance.x); 1208 glyph->fAdvanceX = -SkFDot6ToFloat(fFace->glyph->advance.x);
1198 glyph->fAdvanceY = SkFDot6ToFloat(fFace->glyph->advance.y); 1209 glyph->fAdvanceY = SkFDot6ToFloat(fFace->glyph->advance.y);
1199 } 1210 }
1200 } else { 1211 } else {
1201 if (fDoLinearMetrics) { 1212 if (fDoLinearMetrics) {
1202 const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->line arHoriAdvance); 1213 const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->line arHoriAdvance);
1203 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * adv anceScalar); 1214 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * adv anceScalar);
1204 glyph->fAdvanceY = -SkScalarToFloat(fMatrix22Scalar.getSkewY() * adv anceScalar); 1215 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * adva nceScalar);
1205 } else { 1216 } else {
1206 glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x); 1217 glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x);
1207 glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y); 1218 glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y);
1208 1219
1209 if (fRec.fFlags & kDevKernText_Flag) { 1220 if (fRec.fFlags & kDevKernText_Flag) {
1210 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 1221 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
1211 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1222 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
1212 } 1223 }
1213 } 1224 }
1214 } 1225 }
1215 1226
1216 // If the font isn't scalable, scale the metrics from the non-scalable strik e.
1217 // This means do not try to scale embedded bitmaps; only scale bitmaps in bi tmap only fonts.
1218 if (!FT_IS_SCALABLE(fFace) && !SkScalarNearlyZero(fScale.fY) && fFace->size- >metrics.y_ppem) {
1219 // NOTE: both dimensions are scaled by y_ppem. this is WAI.
1220 scaleGlyphMetrics(*glyph, fScale.fY / fFace->size->metrics.y_ppem);
1221 }
1222
1223 #ifdef ENABLE_GLYPH_SPEW 1227 #ifdef ENABLE_GLYPH_SPEW
1224 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY));
1225 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadG lyphFlags, glyph->fWidth)); 1228 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadG lyphFlags, glyph->fWidth));
1226 #endif 1229 #endif
1227 } 1230 }
1228 1231
1229 static void clear_glyph_image(const SkGlyph& glyph) { 1232 static void clear_glyph_image(const SkGlyph& glyph) {
1230 sk_bzero(glyph.fImage, glyph.rowBytes() * glyph.fHeight); 1233 sk_bzero(glyph.fImage, glyph.rowBytes() * glyph.fHeight);
1231 } 1234 }
1232 1235
1233 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 1236 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
1234 SkAutoMutexAcquire ac(gFTMutex); 1237 SkAutoMutexAcquire ac(gFTMutex);
1235 1238
1236 if (this->setupSize()) { 1239 if (this->setupSize()) {
1237 clear_glyph_image(glyph); 1240 clear_glyph_image(glyph);
1238 return; 1241 return;
1239 } 1242 }
1240 1243
1241 FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags); 1244 FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags);
1242 if (err != 0) { 1245 if (err != 0) {
1243 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph: %d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", 1246 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph: %d width:%d height:%d rb:%d flags:%d) returned 0x%x\n",
1244 glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowByte s(), fLoadGlyphFlags, err)); 1247 glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowByte s(), fLoadGlyphFlags, err));
1245 clear_glyph_image(glyph); 1248 clear_glyph_image(glyph);
1246 return; 1249 return;
1247 } 1250 }
1248 1251
1249 emboldenIfNeeded(fFace, fFace->glyph); 1252 emboldenIfNeeded(fFace, fFace->glyph);
1250 generateGlyphImage(fFace, glyph); 1253 SkMatrix* bitmapMatrix = &fMatrix22Scalar;
1254 SkMatrix subpixelBitmapMatrix;
1255 if (this->shouldSubpixelBitmap(glyph, *bitmapMatrix)) {
1256 subpixelBitmapMatrix = fMatrix22Scalar;
1257 subpixelBitmapMatrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()) ,
1258 SkFixedToScalar(glyph.getSubYFixed()) );
1259 bitmapMatrix = &subpixelBitmapMatrix;
1260 }
1261 generateGlyphImage(fFace, glyph, *bitmapMatrix);
1251 } 1262 }
1252 1263
1253 1264
1254 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path) { 1265 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path) {
1255 SkAutoMutexAcquire ac(gFTMutex); 1266 SkAutoMutexAcquire ac(gFTMutex);
1256 1267
1257 SkASSERT(path); 1268 SkASSERT(path);
1258 1269
1259 if (this->setupSize()) { 1270 if (this->setupSize()) {
1260 path->reset(); 1271 path->reset();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 SkAutoMutexAcquire ac(gFTMutex); 1307 SkAutoMutexAcquire ac(gFTMutex);
1297 1308
1298 if (this->setupSize()) { 1309 if (this->setupSize()) {
1299 sk_bzero(metrics, sizeof(*metrics)); 1310 sk_bzero(metrics, sizeof(*metrics));
1300 return; 1311 return;
1301 } 1312 }
1302 1313
1303 FT_Face face = fFace; 1314 FT_Face face = fFace;
1304 SkScalar scaleX = fScale.x(); 1315 SkScalar scaleX = fScale.x();
1305 SkScalar scaleY = fScale.y(); 1316 SkScalar scaleY = fScale.y();
1306 SkScalar mxy = fMatrix22Scalar.getSkewX() * scaleY; 1317 SkScalar mxy = -fMatrix22Scalar.getSkewX() * scaleY;
1307 SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY; 1318 SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY;
1308 1319
1309 // fetch units/EM from "head" table if needed (ie for bitmap fonts) 1320 // fetch units/EM from "head" table if needed (ie for bitmap fonts)
1310 SkScalar upem = SkIntToScalar(face->units_per_EM); 1321 SkScalar upem = SkIntToScalar(face->units_per_EM);
1311 if (!upem) { 1322 if (!upem) {
1312 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); 1323 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head);
1313 if (ttHeader) { 1324 if (ttHeader) {
1314 upem = SkIntToScalar(ttHeader->Units_Per_EM); 1325 upem = SkIntToScalar(ttHeader->Units_Per_EM);
1315 } 1326 }
1316 } 1327 }
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
1818 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", 1829 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n",
1819 name.c_str(), 1830 name.c_str(),
1820 (skTag >> 24) & 0xFF, 1831 (skTag >> 24) & 0xFF,
1821 (skTag >> 16) & 0xFF, 1832 (skTag >> 16) & 0xFF,
1822 (skTag >> 8) & 0xFF, 1833 (skTag >> 8) & 0xFF,
1823 (skTag) & 0xFF)); 1834 (skTag) & 0xFF));
1824 } 1835 }
1825 } 1836 }
1826 ) 1837 )
1827 } 1838 }
OLDNEW
« no previous file with comments | « no previous file | src/ports/SkFontHost_FreeType_common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698