• 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/SkGraphics.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkScalar.h"
15 #include "include/core/SkSurfaceProps.h"
16 #include "src/core/SkFontPriv.h"
17 #include "src/core/SkGlyphRunPainter.h"
18 #include "src/core/SkReadBuffer.h"
19 
20 #include <tuple>
21 
22 namespace sktext::gpu {
23 
24 #if !defined(SK_DISABLE_SDF_TEXT)
25 // DF sizes and thresholds for usage of the small and medium sizes. For example, above
26 // kSmallDFFontLimit we will use the medium size. The large size is used up until the size at
27 // which we switch over to drawing as paths as controlled by Control.
28 static const int kSmallDFFontLimit = 32;
29 static const int kMediumDFFontLimit = 72;
30 static const int kLargeDFFontLimit = 162;
31 #ifdef SK_BUILD_FOR_MAC
32 static const int kExtraLargeDFFontLimit = 256;
33 #endif
34 
MinSDFTRange(bool useSDFTForSmallText,SkScalar min)35 SkScalar SDFTControl::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) {
36     if (!useSDFTForSmallText) {
37         return kLargeDFFontLimit;
38     }
39     return min;
40 }
41 
SDFTControl(bool ableToUseSDFT,bool useSDFTForSmallText,bool useSDFTForPerspectiveText,SkScalar min,SkScalar max)42 SDFTControl::SDFTControl(
43         bool ableToUseSDFT, bool useSDFTForSmallText, bool useSDFTForPerspectiveText,
44         SkScalar min, SkScalar max)
45         : fMinDistanceFieldFontSize{MinSDFTRange(useSDFTForSmallText, min)}
46         , fMaxDistanceFieldFontSize{max}
47         , fAbleToUseSDFT{ableToUseSDFT}
48         , fAbleToUsePerspectiveSDFT{useSDFTForPerspectiveText} {
49     SkASSERT_RELEASE(0 < min && min <= max);
50 }
51 #endif // !defined(SK_DISABLE_SDF_TEXT)
52 
isDirect(SkScalar approximateDeviceTextSize,const SkPaint & paint,const SkMatrix & matrix) const53 bool SDFTControl::isDirect(SkScalar approximateDeviceTextSize, const SkPaint& paint,
54                            const SkMatrix& matrix) const {
55 #if !defined(SK_DISABLE_SDF_TEXT)
56     const bool isSDFT = this->isSDFT(approximateDeviceTextSize, paint, matrix);
57 #else
58     const bool isSDFT = false;
59 #endif
60     return !isSDFT &&
61            !matrix.hasPerspective() &&
62             0 < approximateDeviceTextSize &&
63             approximateDeviceTextSize < SkGlyphDigest::kSkSideTooBigForAtlas;
64 }
65 
66 #if !defined(SK_DISABLE_SDF_TEXT)
isSDFT(SkScalar approximateDeviceTextSize,const SkPaint & paint,const SkMatrix & matrix) const67 bool SDFTControl::isSDFT(SkScalar approximateDeviceTextSize, const SkPaint& paint,
68                          const SkMatrix& matrix) const {
69     const bool wideStroke = paint.getStyle() == SkPaint::kStroke_Style &&
70             paint.getStrokeWidth() > 0;
71     return fAbleToUseSDFT &&
72            paint.getMaskFilter() == nullptr &&
73             (paint.getStyle() == SkPaint::kFill_Style || wideStroke) &&
74            0 < approximateDeviceTextSize &&
75            (fAbleToUsePerspectiveSDFT || !matrix.hasPerspective()) &&
76            (fMinDistanceFieldFontSize <= approximateDeviceTextSize || matrix.hasPerspective()) &&
77            approximateDeviceTextSize <= fMaxDistanceFieldFontSize;
78 }
79 
80 std::tuple<SkFont, SkScalar, SDFTMatrixRange>
getSDFFont(const SkFont & font,const SkMatrix & viewMatrix,const SkPoint & textLoc) const81 SDFTControl::getSDFFont(const SkFont& font, const SkMatrix& viewMatrix,
82                         const SkPoint& textLoc) const {
83     SkScalar textSize = font.getSize();
84     SkScalar scaledTextSize = SkFontPriv::ApproximateTransformedTextSize(font, viewMatrix, textLoc);
85     if (scaledTextSize <= 0 || SkScalarNearlyEqual(textSize, scaledTextSize)) {
86         scaledTextSize = textSize;
87     }
88 
89     SkFont dfFont{font};
90 
91     SkScalar dfMaskScaleFloor;
92     SkScalar dfMaskScaleCeil;
93     if (scaledTextSize <= kSmallDFFontLimit) {
94         dfMaskScaleFloor = fMinDistanceFieldFontSize;
95         dfMaskScaleCeil = kSmallDFFontLimit;
96     } else if (scaledTextSize <= kMediumDFFontLimit) {
97         dfMaskScaleFloor = kSmallDFFontLimit;
98         dfMaskScaleCeil = kMediumDFFontLimit;
99 #ifdef SK_BUILD_FOR_MAC
100     } else if (scaledTextSize <= kLargeDFFontLimit) {
101         dfMaskScaleFloor = kMediumDFFontLimit;
102         dfMaskScaleCeil = kLargeDFFontLimit;
103     } else {
104         dfMaskScaleFloor = kLargeDFFontLimit;
105         dfMaskScaleCeil = kExtraLargeDFFontLimit;
106     }
107 #else
108     } else {
109         dfMaskScaleFloor = kMediumDFFontLimit;
110         dfMaskScaleCeil = kLargeDFFontLimit;
111     }
112 #endif
113 
114     dfFont.setSize(SkIntToScalar(dfMaskScaleCeil));
115     dfFont.setEdging(SkFont::Edging::kAntiAlias);
116     dfFont.setForceAutoHinting(false);
117     dfFont.setHinting(SkFontHinting::kNormal);
118 
119     // The sub-pixel position will always happen when transforming to the screen.
120     dfFont.setSubpixel(false);
121 
122     SkScalar minMatrixScale = dfMaskScaleFloor / textSize,
123              maxMatrixScale = dfMaskScaleCeil  / textSize;
124     return {dfFont, textSize / dfMaskScaleCeil, {minMatrixScale, maxMatrixScale}};
125 }
126 
matrixInRange(const SkMatrix & matrix) const127 bool SDFTMatrixRange::matrixInRange(const SkMatrix& matrix) const {
128     SkScalar maxScale = matrix.getMaxScale();
129     return fMatrixMin < maxScale && maxScale <= fMatrixMax;
130 }
131 
flatten(SkWriteBuffer & buffer) const132 void SDFTMatrixRange::flatten(SkWriteBuffer& buffer) const {
133     buffer.writeScalar(fMatrixMin);
134     buffer.writeScalar(fMatrixMax);
135 }
136 
MakeFromBuffer(SkReadBuffer & buffer)137 SDFTMatrixRange SDFTMatrixRange::MakeFromBuffer(SkReadBuffer& buffer) {
138     SkScalar min = buffer.readScalar();
139     SkScalar max = buffer.readScalar();
140     return SDFTMatrixRange{min, max};
141 }
142 #endif // !defined(SK_DISABLE_SDF_TEXT)
143 
144 }  // namespace sktext::gpu
145