diff options
-rwxr-xr-x | src/gpu/GrDistanceFieldTextContext.cpp | 39 | ||||
-rwxr-xr-x | src/gpu/effects/GrDistanceFieldTextureEffect.cpp | 123 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldTextureEffect.h | 34 |
3 files changed, 137 insertions, 59 deletions
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index 1fe43200c2..66c97c7dc0 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -271,6 +271,12 @@ inline void GrDistanceFieldTextContext::init(GrRenderTarget* rt, const GrClip& c fSkPaint.setAutohinted(false); fSkPaint.setHinting(SkPaint::kNormal_Hinting); fSkPaint.setSubpixelText(true); + + // fix for skia:3528 + // if we're scaling up, include any scaling to match text size in the view matrix + if (fTextRatio > 1.0f) { + fViewMatrix.preScale(fTextRatio, fTextRatio); + } } void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, @@ -483,13 +489,24 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo kRectToRect_DistanceFieldEffectFlag : 0; bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry()); flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; - + + // fix for skia:3528 + // set the local matrix to correct any text size scaling for gradients et al. + SkMatrix localMatrix; + if (fTextRatio > 1.0f) { + localMatrix.setScale(fTextRatio, fTextRatio); + } else { + localMatrix.reset(); + } + // see if we need to create a new effect if (textureUniqueID != fEffectTextureUniqueID || filteredColor != fEffectColor || flags != fEffectFlags || - !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) { + !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix) || + !fCachedGeometryProcessor->localMatrix().cheapEqualTo(localMatrix)) { GrColor color = fPaint.getColor(); + if (fUseLCDText) { GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); @@ -505,6 +522,7 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo blueCorrection); fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Create(color, fViewMatrix, + localMatrix, fCurrTexture, params, widthAdjust, @@ -518,6 +536,7 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo float correction = fDistanceAdjustTable[lum >> kDistanceAdjustLumShift]; fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(color, fViewMatrix, + localMatrix, fCurrTexture, params, correction, @@ -526,6 +545,7 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo #else fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(color, fViewMatrix, + localMatrix, fCurrTexture, params, flags, @@ -604,12 +624,18 @@ bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset); SkScalar scale = fTextRatio; - dx *= scale; - dy *= scale; + // if we're scaling up, using fix for skia:3528 + if (scale > 1.0f) { + sx /= scale; + sy /= scale; + } else { + dx *= scale; + dy *= scale; + width *= scale; + height *= scale; + } sx += dx; sy += dy; - width *= scale; - height *= scale; SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); // check if we clipped out @@ -643,7 +669,6 @@ bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, this->flush(); SkMatrix ctm; - ctm.setScale(fTextRatio, fTextRatio); ctm.postTranslate(sx - dx, sy - dy); SkPath tmpPath(*glyph->fPath); diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index d44c193260..13ca05271c 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -51,16 +51,6 @@ public: // emit attributes vsBuilder->emitAttributes(dfTexEffect); - GrGLVertToFrag st(kVec2f_GrSLType); - args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); - vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); - - GrGLVertToFrag uv(kVec2f_GrSLType); - args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); - // this is only used with text, so our texture bounds always match the glyph atlas - vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " - GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), - dfTexEffect.inTextureCoords()->fName); #ifdef SK_GAMMA_APPLY_TO_A8 // adjust based on gamma const char* distanceAdjustUniName = NULL; @@ -78,9 +68,36 @@ public: this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); // emit transforms + const SkMatrix& localMatrix = dfTexEffect.localMatrix(); this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, - dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut); + localMatrix, args.fTransformsIn, args.fTransformsOut); + + // add varyings + GrGLVertToFrag recipScale(kFloat_GrSLType); + GrGLVertToFrag st(kVec2f_GrSLType); + bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); + const char* viewMatrixName = this->uViewM(); + // view matrix name is NULL if identity matrix + bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName; + if (isSimilarity && useInverseScale) { + args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision); + vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);", + viewMatrixName, viewMatrixName); + vsBuilder->codeAppend("float tx2 = dot(tx, tx);"); + vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut()); + } else { + args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); + vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); + } + GrGLVertToFrag uv(kVec2f_GrSLType); + args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); + // this is only used with text, so our texture bounds always match the glyph atlas + vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " + GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), + dfTexEffect.inTextureCoords()->fName); + + // Use highp to work around aliasing issues fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, pb->ctxInfo().standard())); @@ -100,16 +117,23 @@ public: fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, pb->ctxInfo().standard())); - fsBuilder->codeAppendf("vec2 st = %s;", st.fsIn()); fsBuilder->codeAppend("float afwidth;"); - if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { + if (isSimilarity) { // For uniform scale, we adjust for the effect of the transformation on the distance + // either by using the inverse scale in the view matrix, or (if there is no view matrix) // by using the length of the gradient of the texture coordinates. We use st coordinates - // to ensure we're mapping 1:1 from texel space to pixel space. + // with the latter to ensure we're mapping 1:1 from texel space to pixel space. // this gives us a smooth step across approximately one fragment - fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));"); + if (useInverseScale) { + fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*%s);", + recipScale.fsIn()); + } else { + fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(%s.x));", + st.fsIn()); + } } else { + fsBuilder->codeAppendf("vec2 st = %s;", st.fsIn()); // For general transforms, to determine the amount of correction we multiply a unit // vector pointing along the SDF gradient direction by the Jacobian of the st coords // (which is the inverse transform for this fragment) and take the length of the result. @@ -170,6 +194,7 @@ public: key |= local.fInputColorType << 16; key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0; key |= ComputePosKey(gp.viewMatrix()) << 25; + key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0; b->add32(key); } @@ -188,13 +213,14 @@ private: GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrColor color, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix, GrTexture* texture, const GrTextureParams& params, #ifdef SK_GAMMA_APPLY_TO_A8 float distanceAdjust, #endif uint32_t flags, bool opaqueVertexColors) - : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors) + : INHERITED(color, viewMatrix, localMatrix, opaqueVertexColors) , fTextureAccess(texture, params) #ifdef SK_GAMMA_APPLY_TO_A8 , fDistanceAdjust(distanceAdjust) @@ -281,6 +307,7 @@ GrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random, return GrDistanceFieldTextureEffect::Create(GrRandomColor(random), GrProcessorUnitTest::TestMatrix(random), + GrProcessorUnitTest::TestMatrix(random), textures[texIdx], params, #ifdef SK_GAMMA_APPLY_TO_A8 random->nextF(), @@ -564,17 +591,6 @@ public: // emit attributes vsBuilder->emitAttributes(dfTexEffect); - GrGLVertToFrag st(kVec2f_GrSLType); - args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); - vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); - - GrGLVertToFrag uv(kVec2f_GrSLType); - args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); - // this is only used with text, so our texture bounds always match the glyph atlas - vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " - GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), - dfTexEffect.inTextureCoords()->fName); - // setup pass through color this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform); @@ -583,9 +599,36 @@ public: this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); // emit transforms + const SkMatrix& localMatrix = dfTexEffect.localMatrix(); this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, - dfTexEffect.localMatrix(), args.fTransformsIn, args.fTransformsOut); + localMatrix, args.fTransformsIn, args.fTransformsOut); + + // set up varyings + bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); + GrGLVertToFrag recipScale(kFloat_GrSLType); + GrGLVertToFrag st(kVec2f_GrSLType); + const char* viewMatrixName = this->uViewM(); + // view matrix name is NULL if identity matrix + bool useInverseScale = !localMatrix.isIdentity() && viewMatrixName; + if (isUniformScale && useInverseScale) { + args.fPB->addVarying("RecipScale", &recipScale, kHigh_GrSLPrecision); + vsBuilder->codeAppendf("vec2 tx = vec2(%s[0][0], %s[1][0]);", + viewMatrixName, viewMatrixName); + vsBuilder->codeAppend("float tx2 = dot(tx, tx);"); + vsBuilder->codeAppendf("%s = inversesqrt(tx2);", recipScale.vsOut()); + } else { + args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); + vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); + } + GrGLVertToFrag uv(kVec2f_GrSLType); + args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); + // this is only used with text, so our texture bounds always match the glyph atlas + vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " + GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), + dfTexEffect.inTextureCoords()->fName); + + // add frag shader code GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); SkAssertResult(fsBuilder->enableFeature( @@ -598,21 +641,24 @@ public: fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, pb->ctxInfo().standard())); - fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); - bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); - if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { fsBuilder->codeAppend("float delta = -" GR_FONT_ATLAS_LCD_DELTA ";\n"); } else { fsBuilder->codeAppend("float delta = " GR_FONT_ATLAS_LCD_DELTA ";\n"); } if (isUniformScale) { - fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n"); - fsBuilder->codeAppend("\tvec2 offset = vec2(dx*delta, 0.0);\n"); + if (useInverseScale) { + fsBuilder->codeAppendf("float dx = %s;", recipScale.fsIn()); + } else { + fsBuilder->codeAppendf("float dx = dFdx(%s.x);", st.fsIn()); + } + fsBuilder->codeAppend("vec2 offset = vec2(dx*delta, 0.0);"); } else { - fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); - fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); - fsBuilder->codeAppend("\tvec2 offset = delta*Jdx;\n"); + fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); + + fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); + fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); + fsBuilder->codeAppend("vec2 offset = delta*Jdx;"); } // green is distance to uv center @@ -721,6 +767,7 @@ public: key |= local.fInputColorType << 16; key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 << 24: 0x0; key |= ComputePosKey(gp.viewMatrix()) << 25; + key |= (!gp.viewMatrix().isIdentity() && !gp.localMatrix().isIdentity()) ? 0x1 << 27 : 0x0; b->add32(key); } @@ -737,10 +784,11 @@ private: GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect( GrColor color, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix, GrTexture* texture, const GrTextureParams& params, DistanceAdjust distanceAdjust, uint32_t flags) - : INHERITED(color, viewMatrix, SkMatrix::I()) + : INHERITED(color, viewMatrix, localMatrix) , fTextureAccess(texture, params) , fDistanceAdjust(distanceAdjust) , fFlags(flags & kLCD_DistanceFieldEffectMask){ @@ -821,6 +869,7 @@ GrGeometryProcessor* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* rando flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), GrProcessorUnitTest::TestMatrix(random), + GrProcessorUnitTest::TestMatrix(random), textures[texIdx], params, wa, flags); diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h index 6be7f9eef3..58d1b77a59 100644 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.h +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h @@ -47,18 +47,20 @@ enum GrDistanceFieldEffectFlags { class GrDistanceFieldTextureEffect : public GrGeometryProcessor { public: #ifdef SK_GAMMA_APPLY_TO_A8 - static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex, - const GrTextureParams& params, + static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix, + GrTexture* tex, const GrTextureParams& params, float lum, uint32_t flags, bool opaqueVertexColors) { - return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, tex, params, lum, - flags, opaqueVertexColors)); + return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, localMatrix, tex, + params, lum, flags, opaqueVertexColors)); } #else - static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex, - const GrTextureParams& params, + static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix, + GrTexture* tex, const GrTextureParams& params, uint32_t flags, bool opaqueVertexColors) { - return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, tex, params, flags, - opaqueVertexColors)); + return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, localMatrix, tex, + params, flags, opaqueVertexColors)); } #endif @@ -88,8 +90,8 @@ public: const GrBatchTracker&) const override; private: - GrDistanceFieldTextureEffect(GrColor, const SkMatrix& viewMatrix, GrTexture* texture, - const GrTextureParams& params, + GrDistanceFieldTextureEffect(GrColor, const SkMatrix& viewMatrix, const SkMatrix& localMatrix, + GrTexture* texture, const GrTextureParams& params, #ifdef SK_GAMMA_APPLY_TO_A8 float distanceAdjust, #endif @@ -194,11 +196,12 @@ public: } }; - static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex, - const GrTextureParams& params, + static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix, + GrTexture* tex, const GrTextureParams& params, DistanceAdjust distanceAdjust, uint32_t flags) { return SkNEW_ARGS(GrDistanceFieldLCDTextureEffect, - (color, viewMatrix, tex, params, distanceAdjust, flags)); + (color, viewMatrix, localMatrix, tex, params, distanceAdjust, flags)); } virtual ~GrDistanceFieldLCDTextureEffect() {} @@ -224,8 +227,9 @@ public: const GrBatchTracker&) const override; private: - GrDistanceFieldLCDTextureEffect(GrColor, const SkMatrix& viewMatrix, GrTexture* texture, - const GrTextureParams& params, + GrDistanceFieldLCDTextureEffect(GrColor, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix, + GrTexture* texture, const GrTextureParams& params, DistanceAdjust wa, uint32_t flags); bool onIsEqual(const GrGeometryProcessor& other) const override; |