• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/text/gpu/SDFTControl.h"
9 
10 #include "include/core/SkFont.h"
11 #include "include/core/SkFontTypes.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkScalar.h"
15 #include "src/core/SkFontPriv.h"
16 #include "src/core/SkGlyph.h"
17 #include "src/core/SkReadBuffer.h"
18 #include "src/core/SkWriteBuffer.h"
19 
20 #include <tuple>
21 
22 struct SkPoint;
23 
24 namespace sktext::gpu {
25 
26 #if !defined(SK_DISABLE_SDF_TEXT)
27 // DF sizes and thresholds for usage of the small and medium sizes. For example, above
28 // kSmallDFFontLimit we will use the medium size. The large size is used up until the size at
29 // which we switch over to drawing as paths as controlled by Control.
30 static const int kSmallDFFontLimit = 32;
31 static const int kMediumDFFontLimit = 72;
32 static const int kLargeDFFontLimit = 162;
33 #ifdef SK_BUILD_FOR_MAC
34 static const int kExtraLargeDFFontLimit = 256;
35 #endif
36 
MinSDFTRange(bool useSDFTForSmallText,SkScalar min)37 SkScalar SDFTControl::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) {
38     if (!useSDFTForSmallText) {
39         return kLargeDFFontLimit;
40     }
41     return min;
42 }
43 
SDFTControl(bool ableToUseSDFT,bool useSDFTForSmallText,bool useSDFTForPerspectiveText,SkScalar min,SkScalar max)44 SDFTControl::SDFTControl(
45         bool ableToUseSDFT, bool useSDFTForSmallText, bool useSDFTForPerspectiveText,
46         SkScalar min, SkScalar max)
47         : fMinDistanceFieldFontSize{MinSDFTRange(useSDFTForSmallText, min)}
48         , fMaxDistanceFieldFontSize{max}
49         , fAbleToUseSDFT{ableToUseSDFT}
50         , fAbleToUsePerspectiveSDFT{useSDFTForPerspectiveText} {
51     SkASSERT_RELEASE(0 < min && min <= max);
52 }
53 #endif // !defined(SK_DISABLE_SDF_TEXT)
54 
isDirect(SkScalar approximateDeviceTextSize,const SkPaint & paint,const SkMatrix & matrix) const55 bool SDFTControl::isDirect(SkScalar approximateDeviceTextSize, const SkPaint& paint,
56                            const SkMatrix& matrix) const {
57 #if !defined(SK_DISABLE_SDF_TEXT)
58     const bool isSDFT = this->isSDFT(approximateDeviceTextSize, paint, matrix);
59 #else
60     const bool isSDFT = false;
61 #endif
62     return !isSDFT &&
63            !matrix.hasPerspective() &&
64             0 < approximateDeviceTextSize &&
65             approximateDeviceTextSize < SkGlyphDigest::kSkSideTooBigForAtlas;
66 }
67 
68 #if !defined(SK_DISABLE_SDF_TEXT)
isSDFT(SkScalar approximateDeviceTextSize,const SkPaint & paint,const SkMatrix & matrix) const69 bool SDFTControl::isSDFT(SkScalar approximateDeviceTextSize, const SkPaint& paint,
70                          const SkMatrix& matrix) const {
71     const bool wideStroke = paint.getStyle() == SkPaint::kStroke_Style &&
72             paint.getStrokeWidth() > 0;
73     return fAbleToUseSDFT &&
74            paint.getMaskFilter() == nullptr &&
75             (paint.getStyle() == SkPaint::kFill_Style || wideStroke) &&
76            0 < approximateDeviceTextSize &&
77            (fAbleToUsePerspectiveSDFT || !matrix.hasPerspective()) &&
78            (fMinDistanceFieldFontSize <= approximateDeviceTextSize || matrix.hasPerspective()) &&
79            approximateDeviceTextSize <= fMaxDistanceFieldFontSize;
80 }
81 
82 std::tuple<SkFont, SkScalar, SDFTMatrixRange>
getSDFFont(const SkFont & font,const SkMatrix & viewMatrix,const SkPoint & textLoc) const83 SDFTControl::getSDFFont(const SkFont& font, const SkMatrix& viewMatrix,
84                         const SkPoint& textLoc) const {
85     SkScalar textSize = font.getSize();
86     SkScalar scaledTextSize = SkFontPriv::ApproximateTransformedTextSize(font, viewMatrix, textLoc);
87     if (scaledTextSize <= 0 || SkScalarNearlyEqual(textSize, scaledTextSize)) {
88         scaledTextSize = textSize;
89     }
90 
91     SkFont dfFont{font};
92 
93     SkScalar dfMaskScaleFloor;
94     SkScalar dfMaskScaleCeil;
95     SkScalar dfMaskSize;
96     if (scaledTextSize <= kSmallDFFontLimit) {
97         dfMaskScaleFloor = fMinDistanceFieldFontSize;
98         dfMaskScaleCeil = kSmallDFFontLimit;
99         dfMaskSize = kSmallDFFontLimit;
100     } else if (scaledTextSize <= kMediumDFFontLimit) {
101         dfMaskScaleFloor = kSmallDFFontLimit;
102         dfMaskScaleCeil = kMediumDFFontLimit;
103         dfMaskSize = kMediumDFFontLimit;
104 #ifdef SK_BUILD_FOR_MAC
105     } else if (scaledTextSize <= kLargeDFFontLimit) {
106         dfMaskScaleFloor = kMediumDFFontLimit;
107         dfMaskScaleCeil = kLargeDFFontLimit;
108         dfMaskSize = kLargeDFFontLimit;
109     } else {
110         dfMaskScaleFloor = kLargeDFFontLimit;
111         dfMaskScaleCeil = fMaxDistanceFieldFontSize;
112         dfMaskSize = kExtraLargeDFFontLimit;
113     }
114 #else
115     } else {
116         dfMaskScaleFloor = kMediumDFFontLimit;
117         dfMaskScaleCeil = fMaxDistanceFieldFontSize;
118         dfMaskSize = kLargeDFFontLimit;
119     }
120 #endif
121 
122     dfFont.setSize(dfMaskSize);
123     dfFont.setEdging(SkFont::Edging::kAntiAlias);
124     dfFont.setForceAutoHinting(false);
125     dfFont.setHinting(SkFontHinting::kNormal);
126 
127     // The sub-pixel position will always happen when transforming to the screen.
128     dfFont.setSubpixel(false);
129 
130     SkScalar minMatrixScale = dfMaskScaleFloor / textSize,
131              maxMatrixScale = dfMaskScaleCeil  / textSize;
132     return {dfFont, textSize / dfMaskSize, {minMatrixScale, maxMatrixScale}};
133 }
134 
matrixInRange(const SkMatrix & matrix) const135 bool SDFTMatrixRange::matrixInRange(const SkMatrix& matrix) const {
136     SkScalar maxScale = matrix.getMaxScale();
137     return fMatrixMin < maxScale && maxScale <= fMatrixMax;
138 }
139 
flatten(SkWriteBuffer & buffer) const140 void SDFTMatrixRange::flatten(SkWriteBuffer& buffer) const {
141     buffer.writeScalar(fMatrixMin);
142     buffer.writeScalar(fMatrixMax);
143 }
144 
MakeFromBuffer(SkReadBuffer & buffer)145 SDFTMatrixRange SDFTMatrixRange::MakeFromBuffer(SkReadBuffer& buffer) {
146     SkScalar min = buffer.readScalar();
147     SkScalar max = buffer.readScalar();
148     return SDFTMatrixRange{min, max};
149 }
150 #endif // !defined(SK_DISABLE_SDF_TEXT)
151 
152 }  // namespace sktext::gpu
153