• 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/gpu/text/GrSDFTControl.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/SkGlyphRunPainter.h"
17 
18 #include <tuple>
19 
20 // DF sizes and thresholds for usage of the small and medium sizes. For example, above
21 // kSmallDFFontLimit we will use the medium size. The large size is used up until the size at
22 // which we switch over to drawing as paths as controlled by Control.
23 static const int kSmallDFFontLimit = 32;
24 static const int kMediumDFFontLimit = 72;
25 static const int kLargeDFFontLimit = 162;
26 #ifdef SK_BUILD_FOR_MAC
27 static const int kExtraLargeDFFontLimit = 256;
28 #endif
29 
MinSDFTRange(bool useSDFTForSmallText,SkScalar min)30 SkScalar GrSDFTControl::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) {
31     if (!useSDFTForSmallText) {
32         return kLargeDFFontLimit;
33     }
34     return min;
35 }
36 
GrSDFTControl(bool ableToUseSDFT,bool useSDFTForSmallText,SkScalar min,SkScalar max)37 GrSDFTControl::GrSDFTControl(
38         bool ableToUseSDFT, bool useSDFTForSmallText, SkScalar min, SkScalar max)
39         : fMinDistanceFieldFontSize{MinSDFTRange(useSDFTForSmallText, min)}
40         , fMaxDistanceFieldFontSize{max}
41         , fAbleToUseSDFT{ableToUseSDFT} {
42     SkASSERT_RELEASE(0 < min && min <= max);
43 }
44 
isDirect(SkScalar approximateDeviceTextSize,const SkPaint & paint) const45 bool GrSDFTControl::isDirect(SkScalar approximateDeviceTextSize, const SkPaint& paint) const {
46     return !isSDFT(approximateDeviceTextSize, paint) &&
47             approximateDeviceTextSize < SkStrikeCommon::kSkSideTooBigForAtlas;
48 }
49 
isSDFT(SkScalar approximateDeviceTextSize,const SkPaint & paint) const50 bool GrSDFTControl::isSDFT(SkScalar approximateDeviceTextSize, const SkPaint& paint) const {
51     return fAbleToUseSDFT &&
52            paint.getMaskFilter() == nullptr &&
53            paint.getStyle() == SkPaint::kFill_Style &&
54            fMinDistanceFieldFontSize <= approximateDeviceTextSize &&
55            approximateDeviceTextSize <= fMaxDistanceFieldFontSize;
56 }
57 
scaled_text_size(const SkScalar textSize,const SkMatrix & viewMatrix)58 SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) {
59     SkScalar scaledTextSize = textSize;
60 
61     if (viewMatrix.hasPerspective()) {
62         // for perspective, we simply force to the medium size
63         // TODO: compute a size based on approximate screen area
64         scaledTextSize = kMediumDFFontLimit;
65     } else {
66         SkScalar maxScale = viewMatrix.getMaxScale();
67         // if we have non-unity scale, we need to choose our base text size
68         // based on the SkPaint's text size multiplied by the max scale factor
69         // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
70         if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
71             scaledTextSize *= maxScale;
72         }
73     }
74 
75     return scaledTextSize;
76 }
77 
78 std::tuple<SkFont, SkScalar, GrSDFTMatrixRange>
getSDFFont(const SkFont & font,const SkMatrix & viewMatrix) const79 GrSDFTControl::getSDFFont(const SkFont& font, const SkMatrix& viewMatrix) const {
80     SkScalar textSize = font.getSize();
81     SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
82 
83     SkFont dfFont{font};
84 
85     SkScalar dfMaskScaleFloor;
86     SkScalar dfMaskScaleCeil;
87     if (scaledTextSize <= kSmallDFFontLimit) {
88         dfMaskScaleFloor = fMinDistanceFieldFontSize;
89         dfMaskScaleCeil = kSmallDFFontLimit;
90     } else if (scaledTextSize <= kMediumDFFontLimit) {
91         dfMaskScaleFloor = kSmallDFFontLimit;
92         dfMaskScaleCeil = kMediumDFFontLimit;
93 #ifdef SK_BUILD_FOR_MAC
94     } else if (scaledTextSize <= kLargeDFFontLimit) {
95         dfMaskScaleFloor = kMediumDFFontLimit;
96         dfMaskScaleCeil = kLargeDFFontLimit;
97     } else {
98         dfMaskScaleFloor = kLargeDFFontLimit;
99         dfMaskScaleCeil = kExtraLargeDFFontLimit;
100     }
101 #else
102     } else {
103         dfMaskScaleFloor = kMediumDFFontLimit;
104         dfMaskScaleCeil = kLargeDFFontLimit;
105     }
106 #endif
107 
108     dfFont.setSize(SkIntToScalar(dfMaskScaleCeil));
109     dfFont.setEdging(SkFont::Edging::kAntiAlias);
110     dfFont.setForceAutoHinting(false);
111     dfFont.setHinting(SkFontHinting::kNormal);
112 
113     // The sub-pixel position will always happen when transforming to the screen.
114     dfFont.setSubpixel(false);
115 
116     SkScalar minMatrixScale = dfMaskScaleFloor / textSize,
117              maxMatrixScale = dfMaskScaleCeil  / textSize;
118     return {dfFont, textSize / dfMaskScaleCeil, {minMatrixScale, maxMatrixScale}};
119 }
120 
matrixInRange(const SkMatrix & matrix) const121 bool GrSDFTMatrixRange::matrixInRange(const SkMatrix& matrix) const {
122     SkScalar maxScale = matrix.getMaxScale();
123     return fMatrixMin < maxScale && maxScale <= fMatrixMax;
124 }
125