aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2015-03-16 11:32:49 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-16 11:32:49 -0700
commit354eba5cb61801130a84378356434d3cc0a4b71a (patch)
tree8a9b58d43ebf04d7f02d6d5ffc62affa08b2cae9
parentdfdec78a5d02e8690998741a9fe5b71a08ca3232 (diff)
Fix SDF gradient calculation for non-uniform xforms
Also adds two non-uniform test cases to the dftext GM. BUG=skia:3540 Review URL: https://codereview.chromium.org/1013773002
-rwxr-xr-xgm/dftext.cpp16
-rwxr-xr-xsrc/gpu/effects/GrDistanceFieldTextureEffect.cpp115
2 files changed, 78 insertions, 53 deletions
diff --git a/gm/dftext.cpp b/gm/dftext.cpp
index 6544e891c9..2ce28c3930 100755
--- a/gm/dftext.cpp
+++ b/gm/dftext.cpp
@@ -196,6 +196,22 @@ protected:
y += paint.getFontMetrics(NULL);
}
+ // check skew
+ {
+ paint.setLCDRenderText(false);
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->skew(0.0f, 0.151515f);
+ paint.setTextSize(32);
+ canvas->drawText(text, textLen, 745, 70, paint);
+ }
+ {
+ paint.setLCDRenderText(true);
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->skew(0.5f, 0.0f);
+ paint.setTextSize(32);
+ canvas->drawText(text, textLen, 580, 230, paint);
+ }
+
// check color emoji
paint.setTypeface(fTypeface);
canvas->drawText(text, textLen, 670, 100, paint);
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 89a634c5c4..c1c84b5871 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -84,39 +84,42 @@ public:
fsBuilder->codeAppend("\tfloat distance = "
SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
- // we adjust for the effect of the transformation on the distance 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.
fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
pb->ctxInfo().standard()));
- fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn());
- fsBuilder->codeAppend("\tfloat afwidth;\n");
+ fsBuilder->codeAppendf("vec2 st = %s;", st.fsIn());
+ fsBuilder->codeAppend("float afwidth;");
if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
+ // For uniform scale, we adjust for the effect of the transformation on the distance
+ // 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.
+
// this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));\n");
+ fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
} else {
- fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
- fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
-
- fsBuilder->codeAppend("\tvec2 uv_grad;\n");
+ // 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.
+ fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
// this is to compensate for the Adreno, which likes to drop tiles on division by 0
- fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
- fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
- fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
- fsBuilder->codeAppend("\t} else {\n");
- fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
- fsBuilder->codeAppend("\t}\n");
+ fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
+ fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
+ fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
+ fsBuilder->codeAppend("} else {");
+ fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
+ fsBuilder->codeAppend("}");
} else {
- fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
+ fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n");
}
- fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
- fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
+ fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
+ fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
+ fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
+ fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
// this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
+ fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
}
- fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
+ fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
#ifdef SK_GAMMA_APPLY_TO_A8
// adjust based on gamma
@@ -368,34 +371,37 @@ public:
fsBuilder->codeAppend("float distance = "
SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
- // we adjust for the effect of the transformation on the distance 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.
fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
pb->ctxInfo().standard()));
fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
fsBuilder->codeAppend("float afwidth;");
if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
+ // For uniform scale, we adjust for the effect of the transformation on the distance
+ // 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.
+
// this gives us a smooth step across approximately one fragment
fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));");
} else {
- fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
- fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
-
- fsBuilder->codeAppend("vec2 uv_grad;");
+ // 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.
+ fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
// this is to compensate for the Adreno, which likes to drop tiles on division by 0
- fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);");
- fsBuilder->codeAppend("if (uv_len2 < 0.0001) {");
- fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);");
+ fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
+ fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
+ fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
fsBuilder->codeAppend("} else {");
- fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);");
+ fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
fsBuilder->codeAppend("}");
} else {
- fsBuilder->codeAppend("uv_grad = normalize(uv);");
+ fsBuilder->codeAppend("dist_grad = normalize(dist_grad);");
}
- fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,");
- fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);");
+ fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
+ fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
+ fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
+ fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
// this gives us a smooth step across approximately one fragment
fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
@@ -648,39 +654,42 @@ public:
fsBuilder->codeAppend("\tdistance = "
"vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
- // we adjust for the effect of the transformation on the distance 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.
-
// To be strictly correct, we should compute the anti-aliasing factor separately
// for each color component. However, this is only important when using perspective
// transformations, and even then using a single factor seems like a reasonable
// trade-off between quality and speed.
- fsBuilder->codeAppend("\tfloat afwidth;\n");
+ fsBuilder->codeAppend("float afwidth;");
if (isUniformScale) {
+ // For uniform scale, we adjust for the effect of the transformation on the distance
+ // 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.
+
// this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dx);\n");
+ fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dx);");
} else {
- fsBuilder->codeAppend("\tvec2 uv_grad;\n");
+ // 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.
+ fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));");
if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
// this is to compensate for the Adreno, which likes to drop tiles on division by 0
- fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
- fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
- fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
- fsBuilder->codeAppend("\t} else {\n");
- fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
- fsBuilder->codeAppend("\t}\n");
+ fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
+ fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
+ fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
+ fsBuilder->codeAppend("} else {");
+ fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
+ fsBuilder->codeAppend("}");
} else {
- fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
+ fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n");
}
- fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
- fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
+ fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,");
+ fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);");
// this gives us a smooth step across approximately one fragment
- fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
+ fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
}
- fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
+ fsBuilder->codeAppend("vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
// adjust based on gamma
const char* textColorUniName = NULL;