1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/text/GrSDFTControl.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 11cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h" 12cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 14cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 15cb93a386Sopenharmony_ci#include "include/core/SkSurfaceProps.h" 16cb93a386Sopenharmony_ci#include "src/core/SkGlyphRunPainter.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#include <tuple> 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci// DF sizes and thresholds for usage of the small and medium sizes. For example, above 21cb93a386Sopenharmony_ci// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at 22cb93a386Sopenharmony_ci// which we switch over to drawing as paths as controlled by Control. 23cb93a386Sopenharmony_cistatic const int kSmallDFFontSize = 32; 24cb93a386Sopenharmony_cistatic const int kSmallDFFontLimit = 32; 25cb93a386Sopenharmony_cistatic const int kMediumDFFontSize = 72; 26cb93a386Sopenharmony_cistatic const int kMediumDFFontLimit = 72; 27cb93a386Sopenharmony_cistatic const int kLargeDFFontSize = 162; 28cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 29cb93a386Sopenharmony_cistatic const int kLargeDFFontLimit = 162; 30cb93a386Sopenharmony_cistatic const int kExtraLargeDFFontSize = 256; 31cb93a386Sopenharmony_ci#endif 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ciSkScalar GrSDFTControl::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) { 34cb93a386Sopenharmony_ci if (!useSDFTForSmallText) { 35cb93a386Sopenharmony_ci return kLargeDFFontSize; 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci return min; 38cb93a386Sopenharmony_ci} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ciGrSDFTControl::GrSDFTControl( 41cb93a386Sopenharmony_ci bool ableToUseSDFT, bool useSDFTForSmallText, SkScalar min, SkScalar max) 42cb93a386Sopenharmony_ci : fMinDistanceFieldFontSize{MinSDFTRange(useSDFTForSmallText, min)} 43cb93a386Sopenharmony_ci , fMaxDistanceFieldFontSize{max} 44cb93a386Sopenharmony_ci , fAbleToUseSDFT{ableToUseSDFT} { 45cb93a386Sopenharmony_ci SkASSERT_RELEASE(0 < min && min <= max); 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ciauto GrSDFTControl::drawingType( 49cb93a386Sopenharmony_ci const SkFont& font, const SkPaint& paint, const SkMatrix& viewMatrix) const -> DrawingType { 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci // Use paths as the first choice for hairlines and perspective. 52cb93a386Sopenharmony_ci if ((paint.getStyle() == SkPaint::kStroke_Style && paint.getStrokeWidth() == 0) 53cb93a386Sopenharmony_ci || viewMatrix.hasPerspective()) { 54cb93a386Sopenharmony_ci return kPath; 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci SkScalar maxScale = viewMatrix.getMaxScale(); 58cb93a386Sopenharmony_ci SkScalar scaledTextSize = maxScale * font.getSize(); 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci // If we can't use SDFT, then make a simple choice between direct or path. 61cb93a386Sopenharmony_ci if (!fAbleToUseSDFT || paint.getMaskFilter() || paint.getStyle() != SkPaint::kFill_Style) { 62cb93a386Sopenharmony_ci constexpr int kAboveIsPath = SkStrikeCommon::kSkSideTooBigForAtlas; 63cb93a386Sopenharmony_ci return scaledTextSize < kAboveIsPath ? kDirect : kPath; 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci // Hinted text looks far better at small resolutions 67cb93a386Sopenharmony_ci // Scaling up beyond 2x yields undesirable artifacts 68cb93a386Sopenharmony_ci#ifdef SKIA_OHOS_FOR_OHOS_TRACE 69cb93a386Sopenharmony_ci if (scaledTextSize <= fMaxDistanceFieldFontSize) { 70cb93a386Sopenharmony_ci#else 71cb93a386Sopenharmony_ci if (scaledTextSize < fMinDistanceFieldFontSize) { 72cb93a386Sopenharmony_ci#endif 73cb93a386Sopenharmony_ci return kDirect; 74cb93a386Sopenharmony_ci } else if (fMaxDistanceFieldFontSize < scaledTextSize) { 75cb93a386Sopenharmony_ci return kPath; 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci return kSDFT; 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciSkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) { 82cb93a386Sopenharmony_ci SkScalar scaledTextSize = textSize; 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci if (viewMatrix.hasPerspective()) { 85cb93a386Sopenharmony_ci // for perspective, we simply force to the medium size 86cb93a386Sopenharmony_ci // TODO: compute a size based on approximate screen area 87cb93a386Sopenharmony_ci scaledTextSize = kMediumDFFontLimit; 88cb93a386Sopenharmony_ci } else { 89cb93a386Sopenharmony_ci SkScalar maxScale = viewMatrix.getMaxScale(); 90cb93a386Sopenharmony_ci // if we have non-unity scale, we need to choose our base text size 91cb93a386Sopenharmony_ci // based on the SkPaint's text size multiplied by the max scale factor 92cb93a386Sopenharmony_ci // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? 93cb93a386Sopenharmony_ci if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { 94cb93a386Sopenharmony_ci scaledTextSize *= maxScale; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci return scaledTextSize; 99cb93a386Sopenharmony_ci} 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ciSkFont GrSDFTControl::getSDFFont(const SkFont& font, 102cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 103cb93a386Sopenharmony_ci SkScalar* textRatio) const { 104cb93a386Sopenharmony_ci SkScalar textSize = font.getSize(); 105cb93a386Sopenharmony_ci SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci SkFont dfFont{font}; 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci if (scaledTextSize <= kSmallDFFontLimit) { 110cb93a386Sopenharmony_ci *textRatio = textSize / kSmallDFFontSize; 111cb93a386Sopenharmony_ci dfFont.setSize(SkIntToScalar(kSmallDFFontSize)); 112cb93a386Sopenharmony_ci } else if (scaledTextSize <= kMediumDFFontLimit) { 113cb93a386Sopenharmony_ci *textRatio = textSize / kMediumDFFontSize; 114cb93a386Sopenharmony_ci dfFont.setSize(SkIntToScalar(kMediumDFFontSize)); 115cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 116cb93a386Sopenharmony_ci } else if (scaledTextSize <= kLargeDFFontLimit) { 117cb93a386Sopenharmony_ci *textRatio = textSize / kLargeDFFontSize; 118cb93a386Sopenharmony_ci dfFont.setSize(SkIntToScalar(kLargeDFFontSize)); 119cb93a386Sopenharmony_ci } else { 120cb93a386Sopenharmony_ci *textRatio = textSize / kExtraLargeDFFontSize; 121cb93a386Sopenharmony_ci dfFont.setSize(SkIntToScalar(kExtraLargeDFFontSize)); 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci#else 124cb93a386Sopenharmony_ci } else { 125cb93a386Sopenharmony_ci *textRatio = textSize / kLargeDFFontSize; 126cb93a386Sopenharmony_ci dfFont.setSize(SkIntToScalar(kLargeDFFontSize)); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci#endif 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci dfFont.setEdging(SkFont::Edging::kAntiAlias); 131cb93a386Sopenharmony_ci dfFont.setForceAutoHinting(false); 132cb93a386Sopenharmony_ci dfFont.setHinting(SkFontHinting::kNormal); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci // The sub-pixel position will always happen when transforming to the screen. 135cb93a386Sopenharmony_ci dfFont.setSubpixel(false); 136cb93a386Sopenharmony_ci return dfFont; 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_cistd::pair<SkScalar, SkScalar> GrSDFTControl::computeSDFMinMaxScale( 140cb93a386Sopenharmony_ci SkScalar textSize, const SkMatrix& viewMatrix) const { 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci // We have three sizes of distance field text, and within each size 'bucket' there is a floor 145cb93a386Sopenharmony_ci // and ceiling. A scale outside of this range would require regenerating the distance fields 146cb93a386Sopenharmony_ci SkScalar dfMaskScaleFloor; 147cb93a386Sopenharmony_ci SkScalar dfMaskScaleCeil; 148cb93a386Sopenharmony_ci if (scaledTextSize <= kSmallDFFontLimit) { 149cb93a386Sopenharmony_ci dfMaskScaleFloor = fMinDistanceFieldFontSize; 150cb93a386Sopenharmony_ci dfMaskScaleCeil = kSmallDFFontLimit; 151cb93a386Sopenharmony_ci } else if (scaledTextSize <= kMediumDFFontLimit) { 152cb93a386Sopenharmony_ci dfMaskScaleFloor = kSmallDFFontLimit; 153cb93a386Sopenharmony_ci dfMaskScaleCeil = kMediumDFFontLimit; 154cb93a386Sopenharmony_ci } else { 155cb93a386Sopenharmony_ci dfMaskScaleFloor = kMediumDFFontLimit; 156cb93a386Sopenharmony_ci dfMaskScaleCeil = fMaxDistanceFieldFontSize; 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci // Because there can be multiple runs in the blob, we want the overall maxMinScale, and 160cb93a386Sopenharmony_ci // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale 161cb93a386Sopenharmony_ci // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can 162cb93a386Sopenharmony_ci // tolerate before we'd have to move to a large mip size. When we actually test these values 163cb93a386Sopenharmony_ci // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test 164cb93a386Sopenharmony_ci // against these values to decide if we can reuse or not(ie, will a given scale change our mip 165cb93a386Sopenharmony_ci // level) 166cb93a386Sopenharmony_ci SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci return std::make_pair(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); 169cb93a386Sopenharmony_ci} 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci 172