diff --git a/third_party/skia/src/gpu/ganesh/ops/AtlasTextOp.cpp b/third_party/skia/src/gpu/ganesh/ops/AtlasTextOp.cpp --- a/third_party/skia/src/gpu/ganesh/ops/AtlasTextOp.cpp +++ b/third_party/skia/src/gpu/ganesh/ops/AtlasTextOp.cpp @@ -44,6 +44,8 @@ #include "src/gpu/ganesh/text/GrAtlasManager.h" #include "src/text/gpu/DistanceFieldAdjustTable.h" #include "src/text/gpu/SubRunContainer.h" +#include "src/text/gpu/VertexFiller.h" +#include "src/core/SkDistanceFieldGen.h" #if defined(SK_GAMMA_APPLY_TO_A8) #include "include/private/base/SkCPUTypes.h" @@ -256,6 +258,28 @@ std::tuple AtlasTextOp::Make(SurfaceDrawContext* sdc if (glyphParams.isSDF) { auto [maskType, DFGPFlags, useGammaCorrectDistanceTable] = calculate_sdf_parameters(*sdc, viewMatrix, glyphParams.isLCD, glyphParams.isAA); + // Bandaid fix: the SDF-LCD fragment shader samples the shared kA8 + // glyph atlas at uv +/- offset where |offset| = (texels-per-device- + // pixel)/3, with no clamp to the glyph's atlas rect + // (GrAtlasedShaderHelpers.h append_multitexture_lookup_lcd). The + // glyph is packed with padding=0 and insetSrc(SK_DistanceFieldInset) + // so the shader may only safely reach SK_DistanceFieldInset texels + // outside the inset rect. The Slug's creationMatrix is deserialized + // unvalidated from a (potentially compromised) renderer; if it + // encodes a strong minification, the offset overshoots into a + // neighbouring glyph belonging to another origin. Drop LCD in that + // case (grayscale SDF does not perform the +/-offset taps). + if (maskType == AtlasTextOp::MaskType::kLCDDistanceField) { + const SkMatrix vd = + subrun->vertexFiller().viewDifference(positionMatrix); + const float texelsPerDevPx = + 1.f / std::max(1e-6f, std::min(std::abs(vd.getScaleX()), + std::abs(vd.getScaleY()))); + if (texelsPerDevPx > 3.f * SK_DistanceFieldInset) { + maskType = AtlasTextOp::MaskType::kGrayscaleDistanceField; + DFGPFlags &= ~kUseLCD_DistanceFieldEffectFlag; + } + } op = GrOp::Make(rContext, maskType, true,