encapsulate GrSDFTOptions better
The logic for picking what type of sub run to create is spread over several locations. Gather that altogether in drawingType(). Have GrSDFT close over all the data needed to calculate the drawing type. This reduces plumbing to the processGlyphRun routine. The next CL should rename GrSDFTOptions to GrSDFTControl. Change-Id: I99e74c11af6d3b3d9919e54fe1e7286fcfbf1bfb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/378036 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
158cab563f
commit
9ad09829f5
@ -49,15 +49,14 @@ class DirectMaskGlyphVertexFillBenchmark : public Benchmark {
|
||||
SkGlyphRunListPainter painter{props, kUnknown_SkColorType,
|
||||
colorSpace.get(), SkStrikeCache::GlobalStrikeCache()};
|
||||
|
||||
GrSDFTOptions options{256, 256};
|
||||
GrSDFTOptions options{false, props.isUseDeviceIndependentFonts(), 256, 256};
|
||||
const SkPoint drawOrigin = glyphRunList.origin();
|
||||
const SkPaint& drawPaint = glyphRunList.paint();
|
||||
|
||||
SkMatrix drawMatrix = view;
|
||||
drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
|
||||
for (auto& glyphRun : glyphRunList) {
|
||||
painter.processGlyphRun(
|
||||
glyphRun, drawMatrix, drawPaint, props, false, options, fBlob.get());
|
||||
painter.processGlyphRun(glyphRun, drawMatrix, drawPaint, options, fBlob.get());
|
||||
}
|
||||
|
||||
SkASSERT(!fBlob->subRunList().isEmpty());
|
||||
|
@ -140,21 +140,15 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
|
||||
void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkPaint& runPaint,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText,
|
||||
const GrSDFTOptions& options,
|
||||
SkGlyphRunPainterInterface* process) {
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
fRejects.setSource(glyphRun.source());
|
||||
const SkFont& runFont = glyphRun.font();
|
||||
|
||||
bool useSDFT = options.canDrawAsDistanceFields(
|
||||
runPaint, runFont, drawMatrix, props, contextSupportsDistanceFieldText);
|
||||
GrSDFTOptions::DrawingType drawingType = options.drawingType(runFont, runPaint, drawMatrix);
|
||||
|
||||
bool usePaths =
|
||||
useSDFT ? false : SkStrikeSpec::ShouldDrawAsPath(runPaint, runFont, drawMatrix);
|
||||
|
||||
if (useSDFT) {
|
||||
if (drawingType == GrSDFTOptions::kSDFT) {
|
||||
// Process SDFT - This should be the .009% case.
|
||||
const auto& [strikeSpec, minScale, maxScale] =
|
||||
SkStrikeSpec::MakeSDFT(runFont, runPaint, fDeviceProps, drawMatrix, options);
|
||||
@ -175,7 +169,7 @@ void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
}
|
||||
}
|
||||
|
||||
if (!usePaths && !fRejects.source().empty()) {
|
||||
if (drawingType != GrSDFTOptions::kPath && !fRejects.source().empty()) {
|
||||
// Process masks including ARGB - this should be the 99.99% case.
|
||||
|
||||
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
|
||||
|
@ -86,8 +86,6 @@ public:
|
||||
void processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkPaint& drawPaint,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText,
|
||||
const GrSDFTOptions& options,
|
||||
SkGlyphRunPainterInterface* process);
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
@ -819,7 +819,10 @@ protected:
|
||||
#if SK_SUPPORT_GPU
|
||||
GrContextOptions ctxOptions;
|
||||
GrSDFTOptions options =
|
||||
{ctxOptions.fMinDistanceFieldFontSize, ctxOptions.fGlyphsAsPathsFontSize};
|
||||
GrSDFTOptions{fDFTSupport,
|
||||
this->surfaceProps().isUseDeviceIndependentFonts(),
|
||||
ctxOptions.fMinDistanceFieldFontSize,
|
||||
ctxOptions.fGlyphsAsPathsFontSize};
|
||||
|
||||
SkMatrix drawMatrix = this->localToDevice();
|
||||
drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
|
||||
@ -827,8 +830,6 @@ protected:
|
||||
fPainter.processGlyphRun(glyphRun,
|
||||
drawMatrix,
|
||||
glyphRunList.paint(),
|
||||
this->surfaceProps(),
|
||||
fDFTSupport,
|
||||
options,
|
||||
nullptr);
|
||||
}
|
||||
|
@ -7,8 +7,17 @@
|
||||
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
|
||||
#include "src/gpu/GrCaps.h"
|
||||
#include "src/gpu/GrDrawingManager.h"
|
||||
|
||||
void GrRecordingContextPriv::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) {
|
||||
fContext->drawingManager()->moveRenderTasksToDDL(ddl);
|
||||
}
|
||||
|
||||
GrSDFTOptions GrRecordingContextPriv::getSDFTOptions(bool useSDFTForSmallText) const {
|
||||
return GrSDFTOptions{
|
||||
this->caps()->shaderCaps()->supportsDistanceFieldText(),
|
||||
useSDFTForSmallText,
|
||||
this->options().fMinDistanceFieldFontSize,
|
||||
this->options().fGlyphsAsPathsFontSize};
|
||||
}
|
||||
|
@ -102,9 +102,7 @@ public:
|
||||
return &fContext->fStats;
|
||||
}
|
||||
|
||||
GrSDFTOptions SDFTOptions() const {
|
||||
return {this->options().fMinDistanceFieldFontSize, this->options().fGlyphsAsPathsFontSize};
|
||||
}
|
||||
GrSDFTOptions getSDFTOptions(bool useSDFTForSmallText) const;
|
||||
|
||||
/**
|
||||
* Create a GrRecordingContext without a resource cache
|
||||
|
@ -364,7 +364,10 @@ void GrSurfaceDrawContext::drawGlyphRunList(const GrClip* clip,
|
||||
return;
|
||||
}
|
||||
|
||||
GrSDFTOptions options = fContext->priv().SDFTOptions();
|
||||
GrSDFTOptions options =
|
||||
this->recordingContext()->priv().getSDFTOptions(
|
||||
this->surfaceProps().isUseDeviceIndependentFonts());
|
||||
|
||||
GrTextBlobCache* textBlobCache = fContext->priv().getTextBlobCache();
|
||||
|
||||
// Get the first paint to use as the key paint.
|
||||
@ -424,13 +427,10 @@ void GrSurfaceDrawContext::drawGlyphRunList(const GrClip* clip,
|
||||
}
|
||||
|
||||
blob = GrTextBlob::Make(glyphRunList, drawMatrix);
|
||||
bool supportsSDFT = fContext->priv().caps()->shaderCaps()->supportsDistanceFieldText();
|
||||
blob->makeSubRuns(&fGlyphPainter,
|
||||
glyphRunList,
|
||||
drawMatrix,
|
||||
drawPaint,
|
||||
fSurfaceProps,
|
||||
supportsSDFT,
|
||||
options);
|
||||
|
||||
if (canCache) {
|
||||
|
@ -483,7 +483,8 @@ GrOp::Owner GrAtlasTextOp::CreateOpTestingOnly(GrSurfaceDrawContext* rtc,
|
||||
}
|
||||
|
||||
auto rContext = rtc->recordingContext();
|
||||
GrSDFTOptions SDFOptions = rContext->priv().SDFTOptions();
|
||||
GrSDFTOptions SDFOptions =
|
||||
rContext->priv().getSDFTOptions(rtc->surfaceProps().isUseDeviceIndependentFonts());
|
||||
|
||||
sk_sp<GrTextBlob> blob = GrTextBlob::Make(glyphRunList, drawMatrix);
|
||||
SkGlyphRunListPainter* painter = rtc->glyphRunPainter();
|
||||
@ -491,9 +492,8 @@ GrOp::Owner GrAtlasTextOp::CreateOpTestingOnly(GrSurfaceDrawContext* rtc,
|
||||
*glyphRunList.begin(),
|
||||
drawMatrix,
|
||||
glyphRunList.paint(),
|
||||
rtc->surfaceProps(),
|
||||
rContext->priv().caps()->shaderCaps()->supportsDistanceFieldText(),
|
||||
SDFOptions, blob.get());
|
||||
SDFOptions,
|
||||
blob.get());
|
||||
if (blob->subRunList().isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -8,10 +8,12 @@
|
||||
#include "src/gpu/text/GrSDFTOptions.h"
|
||||
|
||||
#include "include/core/SkFont.h"
|
||||
#include "include/core/SkGraphics.h"
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkSurfaceProps.h"
|
||||
#include "src/core/SkGlyphRunPainter.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
@ -28,50 +30,49 @@ static const int kLargeDFFontLimit = 162;
|
||||
static const int kExtraLargeDFFontSize = 256;
|
||||
#endif
|
||||
|
||||
GrSDFTOptions::GrSDFTOptions(SkScalar min, SkScalar max)
|
||||
: fMinDistanceFieldFontSize{min}
|
||||
, fMaxDistanceFieldFontSize{max} {
|
||||
SkASSERT_RELEASE(min > 0 && max >= min);
|
||||
SkScalar GrSDFTOptions::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) {
|
||||
if (!useSDFTForSmallText) {
|
||||
return kLargeDFFontSize;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
bool GrSDFTOptions::canDrawAsDistanceFields(const SkPaint& paint, const SkFont& font,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText) const {
|
||||
// mask filters modify alpha, which doesn't translate well to distance
|
||||
if (paint.getMaskFilter() || !contextSupportsDistanceFieldText) {
|
||||
return false;
|
||||
GrSDFTOptions::GrSDFTOptions(
|
||||
bool ableToUseSDFT, bool useSDFTForSmallText, SkScalar min, SkScalar max)
|
||||
: fMinDistanceFieldFontSize{MinSDFTRange(useSDFTForSmallText, min)}
|
||||
, fMaxDistanceFieldFontSize{max}
|
||||
, fAbleToUseSDFT{ableToUseSDFT} {
|
||||
SkASSERT_RELEASE(0 < min && min <= max);
|
||||
}
|
||||
|
||||
auto GrSDFTOptions::drawingType(
|
||||
const SkFont& font, const SkPaint& paint, const SkMatrix& viewMatrix) const -> DrawingType {
|
||||
|
||||
// Use paths as the first choice for hairlines and perspective.
|
||||
if ((paint.getStyle() == SkPaint::kStroke_Style && paint.getStrokeWidth() == 0)
|
||||
|| viewMatrix.hasPerspective()) {
|
||||
return kPath;
|
||||
}
|
||||
|
||||
// TODO: add some stroking support
|
||||
if (paint.getStyle() != SkPaint::kFill_Style) {
|
||||
return false;
|
||||
SkScalar maxScale = viewMatrix.getMaxScale();
|
||||
SkScalar scaledTextSize = maxScale * font.getSize();
|
||||
|
||||
// If we can't use SDFT, then make a simple choice between direct or path.
|
||||
if (!fAbleToUseSDFT || paint.getMaskFilter() || paint.getStyle() != SkPaint::kFill_Style) {
|
||||
const int kAboveIsPath = std::min(SkGraphics::GetFontCachePointSizeLimit(),
|
||||
(int)SkStrikeCommon::kSkSideTooBigForAtlas);
|
||||
return scaledTextSize < kAboveIsPath ? kDirect : kPath;
|
||||
}
|
||||
|
||||
if (viewMatrix.hasPerspective()) {
|
||||
// Don't use SDF for perspective. Paths look better.
|
||||
return false;
|
||||
} else {
|
||||
SkScalar maxScale = viewMatrix.getMaxScale();
|
||||
SkScalar scaledTextSize = maxScale * font.getSize();
|
||||
// Hinted text looks far better at small resolutions
|
||||
// Scaling up beyond 2x yields undesirable artifacts
|
||||
if (scaledTextSize < fMinDistanceFieldFontSize ||
|
||||
scaledTextSize > fMaxDistanceFieldFontSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool useDFT = props.isUseDeviceIndependentFonts();
|
||||
#if SK_FORCE_DISTANCE_FIELD_TEXT
|
||||
useDFT = true;
|
||||
#endif
|
||||
|
||||
if (!useDFT && scaledTextSize < kLargeDFFontSize) {
|
||||
return false;
|
||||
}
|
||||
// Hinted text looks far better at small resolutions
|
||||
// Scaling up beyond 2x yields undesirable artifacts
|
||||
if (scaledTextSize < fMinDistanceFieldFontSize) {
|
||||
return kDirect;
|
||||
} else if (fMaxDistanceFieldFontSize < scaledTextSize) {
|
||||
return kPath;
|
||||
}
|
||||
|
||||
return true;
|
||||
return kSDFT;
|
||||
}
|
||||
|
||||
SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) {
|
||||
|
@ -16,23 +16,33 @@ class SkSurfaceProps;
|
||||
|
||||
class GrSDFTOptions {
|
||||
public:
|
||||
GrSDFTOptions(SkScalar min, SkScalar max);
|
||||
GrSDFTOptions(bool ableToUseSDFT, bool useSDFTForSmallText, SkScalar min, SkScalar max);
|
||||
|
||||
enum DrawingType {
|
||||
kDirect,
|
||||
kSDFT,
|
||||
kPath
|
||||
};
|
||||
|
||||
DrawingType drawingType(
|
||||
const SkFont& font, const SkPaint& paint, const SkMatrix& viewMatrix) const;
|
||||
|
||||
bool canDrawAsDistanceFields(const SkPaint&, const SkFont&, const SkMatrix& viewMatrix,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText) const;
|
||||
SkFont getSDFFont(const SkFont& font,
|
||||
const SkMatrix& viewMatrix,
|
||||
SkScalar* textRatio) const;
|
||||
std::pair<SkScalar, SkScalar> computeSDFMinMaxScale(
|
||||
SkScalar textSize, const SkMatrix& viewMatrix) const;
|
||||
private:
|
||||
static SkScalar MinSDFTRange(bool useSDFTForSmallText, SkScalar min);
|
||||
|
||||
// Below this size (in device space) distance field text will not be used.
|
||||
const SkScalar fMinDistanceFieldFontSize;
|
||||
|
||||
// Above this size (in device space) distance field text will not be used and glyphs will
|
||||
// be rendered from outline as individual paths.
|
||||
const SkScalar fMaxDistanceFieldFontSize;
|
||||
|
||||
const bool fAbleToUseSDFT;
|
||||
};
|
||||
|
||||
#endif // GrSDFTOptions_DEFINED
|
||||
|
@ -1492,15 +1492,11 @@ void GrTextBlob::makeSubRuns(SkGlyphRunListPainter* painter,
|
||||
const SkGlyphRunList& glyphRunList,
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkPaint& runPaint,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText,
|
||||
const GrSDFTOptions& options) {
|
||||
for (auto& glyphRun : glyphRunList) {
|
||||
painter->processGlyphRun(glyphRun,
|
||||
drawMatrix,
|
||||
runPaint,
|
||||
props,
|
||||
contextSupportsDistanceFieldText,
|
||||
options,
|
||||
this);
|
||||
}
|
||||
|
@ -404,8 +404,6 @@ public:
|
||||
const SkGlyphRunList& glyphRunList,
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkPaint& runPaint,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText,
|
||||
const GrSDFTOptions& options);
|
||||
|
||||
static const Key& GetKey(const GrTextBlob& blob);
|
||||
|
@ -683,10 +683,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, c
|
||||
|
||||
// A scale transform forces fallback to dft.
|
||||
SkMatrix matrix = SkMatrix::Scale(16, 16);
|
||||
SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
|
||||
GrSDFTOptions options = direct->priv().asRecordingContext()->priv().SDFTOptions();
|
||||
REPORTER_ASSERT(reporter,
|
||||
options.canDrawAsDistanceFields(paint, font, matrix, surfaceProps, true));
|
||||
GrSDFTOptions options = direct->priv().asRecordingContext()->priv().getSDFTOptions(true);
|
||||
REPORTER_ASSERT(reporter, options.drawingType(font, paint, matrix) == GrSDFTOptions::kSDFT);
|
||||
|
||||
// Server.
|
||||
auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
|
||||
|
Loading…
Reference in New Issue
Block a user