diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp index f0f4ec4fa3..c8dd4ebd77 100644 --- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp +++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp @@ -77,6 +77,8 @@ public: bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); bool isGammaCorrect = SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag); + bool isAliased = + SkToBool(dfTexEffect.getFlags() & kAliased_DistanceFieldEffectFlag); varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName); @@ -158,10 +160,12 @@ public: fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); } - // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are - // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance - // mapped linearly to coverage, so use a linear step: - if (isGammaCorrect) { + if (isAliased) { + fragBuilder->codeAppend("float val = distance > 0 ? 1.0 : 0.0;"); + } else if (isGammaCorrect) { + // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are + // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want + // distance mapped linearly to coverage, so use a linear step: fragBuilder->codeAppend( "float val = clamp((distance + afwidth) / (2.0 * afwidth), 0.0, 1.0);"); } else { diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h index 3f616e9480..344ac4a092 100644 --- a/src/gpu/effects/GrDistanceFieldGeoProc.h +++ b/src/gpu/effects/GrDistanceFieldGeoProc.h @@ -23,6 +23,7 @@ enum GrDistanceFieldEffectFlags { kBGR_DistanceFieldEffectFlag = 0x08, // lcd display has bgr order kPortrait_DistanceFieldEffectFlag = 0x10, // lcd display is in portrait mode (not used yet) kGammaCorrect_DistanceFieldEffectFlag = 0x20, // assume gamma-correct output (linear blending) + kAliased_DistanceFieldEffectFlag = 0x40, // monochrome output kInvalid_DistanceFieldEffectFlag = 0x80, // invalid state (for initialization) @@ -31,7 +32,8 @@ enum GrDistanceFieldEffectFlags { // The subset of the flags relevant to GrDistanceFieldA8TextGeoProc kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | kScaleOnly_DistanceFieldEffectFlag | - kGammaCorrect_DistanceFieldEffectFlag, + kGammaCorrect_DistanceFieldEffectFlag | + kAliased_DistanceFieldEffectFlag, // The subset of the flags relevant to GrDistanceFieldLCDTextGeoProc kLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | kScaleOnly_DistanceFieldEffectFlag | diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index 20a5b4f5d8..9c4172ceaf 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -47,12 +47,14 @@ void GrAtlasTextOp::getProcessorAnalysisInputs(GrProcessorAnalysisColor* color, color->setToConstant(fColor); } switch (fMaskType) { - case kGrayscaleDistanceField_MaskType: case kGrayscaleCoverageMask_MaskType: + case kAliasedDistanceField_MaskType: + case kGrayscaleDistanceField_MaskType: *coverage = GrProcessorAnalysisCoverage::kSingleChannel; break; case kLCDCoverageMask_MaskType: case kLCDDistanceField_MaskType: + case kLCDBGRDistanceField_MaskType: *coverage = GrProcessorAnalysisCoverage::kLCD; break; case kColorBitmapMask_MaskType: @@ -174,10 +176,6 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { if (fLuminanceColor != that->fLuminanceColor) { return false; } - - if (fUseBGR != that->fUseBGR) { - return false; - } } fNumGlyphs += that->numGlyphs(); @@ -221,11 +219,12 @@ sk_sp GrAtlasTextOp::setupDfProcessor(const SkMatrix& viewM uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; flags |= viewMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0; flags |= fUseGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0; + flags |= (kAliasedDistanceField_MaskType == fMaskType) ? kAliased_DistanceFieldEffectFlag : 0; // see if we need to create a new effect if (isLCD) { flags |= kUseLCD_DistanceFieldEffectFlag; - flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0; + flags |= (kLCDBGRDistanceField_MaskType == fMaskType) ? kBGR_DistanceFieldEffectFlag : 0; float redCorrection = fDistanceAdjustTable->getAdjustment( SkColorGetR(luminanceColor) >> kDistanceAdjustLumShift, @@ -245,9 +244,12 @@ sk_sp GrAtlasTextOp::setupDfProcessor(const SkMatrix& viewM this->usesLocalCoords()); } else { #ifdef SK_GAMMA_APPLY_TO_A8 - U8CPU lum = SkColorSpaceLuminance::computeLuminance(SK_GAMMA_EXPONENT, luminanceColor); - float correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift, - fUseGammaCorrectDistanceTable); + float correction = 0; + if (kAliasedDistanceField_MaskType != fMaskType) { + U8CPU lum = SkColorSpaceLuminance::computeLuminance(SK_GAMMA_EXPONENT, luminanceColor); + correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift, + fUseGammaCorrectDistanceTable); + } return GrDistanceFieldA8TextGeoProc::Make(color, viewMatrix, std::move(proxy), params, correction, flags, diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h index fcb3db1fca..24166a19d9 100644 --- a/src/gpu/ops/GrAtlasTextOp.h +++ b/src/gpu/ops/GrAtlasTextOp.h @@ -57,22 +57,24 @@ public: op->fGeoCount = 1; op->fLuminanceColor = 0; op->fFontCache = fontCache; - op->fUseBGR = false; return op; } static std::unique_ptr MakeDistanceField( int glyphCount, GrAtlasGlyphCache* fontCache, const GrDistanceFieldAdjustTable* distanceAdjustTable, - bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR) { + bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR, + bool isAntiAliased) { std::unique_ptr op(new GrAtlasTextOp); op->fFontCache = fontCache; - op->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistanceField_MaskType; + op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType + : isLCD ? (useBGR ? kLCDBGRDistanceField_MaskType + : kLCDDistanceField_MaskType) + : kGrayscaleDistanceField_MaskType; op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable; op->fLuminanceColor = luminanceColor; - op->fUseBGR = useBGR; op->fNumGlyphs = glyphCount; op->fGeoCount = 1; return op; @@ -122,20 +124,26 @@ private: case kColorBitmapMask_MaskType: return kARGB_GrMaskFormat; case kGrayscaleCoverageMask_MaskType: + case kAliasedDistanceField_MaskType: case kGrayscaleDistanceField_MaskType: case kLCDDistanceField_MaskType: + case kLCDBGRDistanceField_MaskType: return kA8_GrMaskFormat; } return kA8_GrMaskFormat; // suppress warning } bool usesDistanceFields() const { - return kGrayscaleDistanceField_MaskType == fMaskType || - kLCDDistanceField_MaskType == fMaskType; + return kAliasedDistanceField_MaskType == fMaskType || + kGrayscaleDistanceField_MaskType == fMaskType || + kLCDDistanceField_MaskType == fMaskType || + kLCDBGRDistanceField_MaskType == fMaskType; } bool isLCD() const { - return kLCDCoverageMask_MaskType == fMaskType || kLCDDistanceField_MaskType == fMaskType; + return kLCDCoverageMask_MaskType == fMaskType || + kLCDDistanceField_MaskType == fMaskType || + kLCDBGRDistanceField_MaskType == fMaskType; } inline void flush(GrLegacyMeshDrawOp::Target* target, FlushInfo* flushInfo) const; @@ -164,10 +172,11 @@ private: kGrayscaleCoverageMask_MaskType, kLCDCoverageMask_MaskType, kColorBitmapMask_MaskType, + kAliasedDistanceField_MaskType, kGrayscaleDistanceField_MaskType, kLCDDistanceField_MaskType, + kLCDBGRDistanceField_MaskType, } fMaskType; - bool fUseBGR; // fold this into the enum? GrAtlasGlyphCache* fFontCache; diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp index a68f6f9cfa..10b1c81639 100644 --- a/src/gpu/text/GrAtlasTextBlob.cpp +++ b/src/gpu/text/GrAtlasTextBlob.cpp @@ -270,7 +270,7 @@ inline std::unique_ptr GrAtlasTextBlob::makeOp( bool useBGR = SkPixelGeometryIsBGR(props.pixelGeometry()); op = GrAtlasTextOp::MakeDistanceField(glyphCount, cache, distanceAdjustTable, useGammaCorrectDistanceTable, luminanceColor, - info.hasUseLCDText(), useBGR); + info.hasUseLCDText(), useBGR, info.isAntiAliased()); } else { op = GrAtlasTextOp::MakeBitmap(format, glyphCount, cache); } diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h index 470d26f457..12fe68b948 100644 --- a/src/gpu/text/GrAtlasTextBlob.h +++ b/src/gpu/text/GrAtlasTextBlob.h @@ -126,10 +126,11 @@ public: } // sets the last subrun of runIndex to use distance field text - void setSubRunHasDistanceFields(int runIndex, bool hasLCD) { + void setSubRunHasDistanceFields(int runIndex, bool hasLCD, bool isAntiAlias) { Run& run = fRuns[runIndex]; Run::SubRunInfo& subRun = run.fSubRunInfo.back(); subRun.setUseLCDText(hasLCD); + subRun.setAntiAliased(isAntiAlias); subRun.setDrawAsDistanceFields(); } @@ -358,8 +359,7 @@ private: , fGlyphEndIndex(0) , fColor(GrColor_ILLEGAL) , fMaskFormat(kA8_GrMaskFormat) - , fDrawAsDistanceFields(false) - , fUseLCDText(false) { + , fFlags(0) { fVertexBounds.setLargestInverted(); } SubRunInfo(const SubRunInfo& that) @@ -376,8 +376,7 @@ private: , fY(that.fY) , fColor(that.fColor) , fMaskFormat(that.fMaskFormat) - , fDrawAsDistanceFields(that.fDrawAsDistanceFields) - , fUseLCDText(that.fUseLCDText) { + , fFlags(that.fFlags) { } // TODO when this object is more internal, drop the privacy @@ -432,12 +431,24 @@ private: SkScalar*transX, SkScalar* transY); // df properties - void setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; } - bool hasUseLCDText() const { return fUseLCDText; } - void setDrawAsDistanceFields() { fDrawAsDistanceFields = true; } - bool drawAsDistanceFields() const { return fDrawAsDistanceFields; } + void setDrawAsDistanceFields() { fFlags |= kDrawAsSDF_Flag; } + bool drawAsDistanceFields() const { return SkToBool(fFlags & kDrawAsSDF_Flag); } + void setUseLCDText(bool useLCDText) { + fFlags = useLCDText ? fFlags | kUseLCDText_Flag : fFlags & ~kUseLCDText_Flag; + } + bool hasUseLCDText() const { return SkToBool(fFlags & kUseLCDText_Flag); } + void setAntiAliased(bool antiAliased) { + fFlags = antiAliased ? fFlags | kAntiAliased_Flag : fFlags & ~kAntiAliased_Flag; + } + bool isAntiAliased() const { return SkToBool(fFlags & kAntiAliased_Flag); } private: + enum Flag { + kDrawAsSDF_Flag = 0x1, + kUseLCDText_Flag = 0x2, + kAntiAliased_Flag = 0x4 + }; + GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken; sk_sp fStrike; SkMatrix fCurrentViewMatrix; @@ -451,8 +462,7 @@ private: SkScalar fY; GrColor fColor; GrMaskFormat fMaskFormat; - bool fDrawAsDistanceFields; // df property - bool fUseLCDText; // df property + uint32_t fFlags; }; SubRunInfo& push_back() { diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp index 20d5aaf338..7ef7eb8587 100644 --- a/src/gpu/text/GrTextUtils.cpp +++ b/src/gpu/text/GrTextUtils.cpp @@ -283,6 +283,7 @@ void GrTextUtils::InitDistanceFieldPaint(GrAtlasTextBlob* blob, SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); blob->setMinAndMaxScale(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); + skPaint->setAntiAlias(true); skPaint->setLCDRenderText(false); skPaint->setAutohinted(false); skPaint->setHinting(SkPaint::kNormal_Hinting); @@ -386,7 +387,8 @@ void GrTextUtils::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyp SkPaint dfPaint(paint); GrTextUtils::InitDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix); blob->setHasDistanceField(); - blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText()); + blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), + paint.skPaint().isAntiAlias()); GrAtlasTextStrike* currStrike = nullptr;