aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2014-09-16 05:45:19 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-09-16 05:45:19 -0700
commit9564ce60a657acce89fb956deb8645b324eaad1e (patch)
tree0fbe408f717124b40ef6c0822828c6d5371fcf0e
parent49005bf8929dd8ca86431e13414d683b509cd538 (diff)
Fix scaling issue with distance field text.
Picks the correct distance field size based on both the text size and the max matrix scale. Adjusts the matrix scale if non-unity. Also adds GM for verifying proper distance field scaling. BUG=skia:2928 R=bsalomon@google.com, joshualitt@google.com Author: jvanverth@google.com Review URL: https://codereview.chromium.org/568843002
-rwxr-xr-xgm/dftext.cpp165
-rw-r--r--gm/fontscaler.cpp2
-rw-r--r--gyp/gmslides.gypi1
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp31
-rw-r--r--src/gpu/GrDistanceFieldTextContext.h1
-rwxr-xr-xsrc/gpu/effects/GrDistanceFieldTextureEffect.cpp9
6 files changed, 197 insertions, 12 deletions
diff --git a/gm/dftext.cpp b/gm/dftext.cpp
new file mode 100755
index 0000000000..65e64a9093
--- /dev/null
+++ b/gm/dftext.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "gm.h"
+#include "SkSurface.h"
+#include "SkTypeface.h"
+
+namespace skiagm {
+
+class DFTextGM : public GM {
+public:
+ DFTextGM() {
+ this->setBGColor(0xFFFFFFFF);
+ }
+
+ virtual ~DFTextGM() {
+ }
+
+protected:
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ return kGPUOnly_Flag;
+ }
+
+ virtual SkString onShortName() {
+ return SkString("dftext");
+ }
+
+ virtual SkISize onISize() {
+ return SkISize::Make(1024, 768);
+ }
+
+ static void rotate_about(SkCanvas* canvas,
+ SkScalar degrees,
+ SkScalar px, SkScalar py) {
+ canvas->translate(px, py);
+ canvas->rotate(degrees);
+ canvas->translate(-px, -py);
+ }
+
+ virtual void onDraw(SkCanvas* inputCanvas) {
+ SkScalar textSizes[] = { 11.0f, 11.0f*2.0f, 11.0f*5.0f, 11.0f*2.0f*5.0f };
+ SkScalar scales[] = { 2.0f*5.0f, 5.0f, 2.0f, 1.0f };
+
+ // set up offscreen rendering with distance field text
+#if SK_SUPPORT_GPU
+ GrContext* ctx = inputCanvas->getGrContext();
+ SkImageInfo info = SkImageInfo::MakeN32Premul(onISize());
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, info, 0,
+ SkSurface::kDistanceField_TextRenderMode));
+ SkCanvas* canvas = surface->getCanvas();
+#else
+ SkCanvas* canvas = inputCanvas;
+#endif
+ canvas->clear(0xffffffff);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setSubpixelText(true);
+#if !SK_SUPPORT_GPU
+ paint.setDistanceFieldTextTEMP(true);
+#endif
+ sk_tool_utils::set_portable_typeface(&paint, "Times New Roman", SkTypeface::kNormal);
+
+ const char* text = "Hamburgefons";
+ const size_t textLen = strlen(text);
+
+ // check scaling up
+ SkScalar x = SkIntToScalar(0);
+ SkScalar y = SkIntToScalar(78);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(textSizes); ++i) {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(x, y);
+ canvas->scale(scales[i], scales[i]);
+ paint.setTextSize(textSizes[i]);
+ canvas->drawText(text, textLen, 0, 0, paint);
+ y += paint.getFontMetrics(NULL)*scales[i];
+ }
+
+ // check rotation
+ for (size_t i = 0; i < 5; ++i) {
+ SkScalar rotX = SkIntToScalar(10);
+ SkScalar rotY = y;
+
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(SkIntToScalar(10 + i * 200), -80);
+ rotate_about(canvas, SkIntToScalar(i * 5), rotX, rotY);
+ for (int ps = 6; ps <= 32; ps += 3) {
+ paint.setTextSize(SkIntToScalar(ps));
+ canvas->drawText(text, textLen, rotX, rotY, paint);
+ rotY += paint.getFontMetrics(NULL);
+ }
+ }
+
+ // check scaling down
+ paint.setLCDRenderText(true);
+ x = SkIntToScalar(700);
+ y = SkIntToScalar(20);
+ size_t arraySize = SK_ARRAY_COUNT(textSizes);
+ for (size_t i = 0; i < arraySize; ++i) {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(x, y);
+ SkScalar scaleFactor = SkScalarInvert(scales[arraySize - i - 1]);
+ canvas->scale(scaleFactor, scaleFactor);
+ paint.setTextSize(textSizes[i]);
+ canvas->drawText(text, textLen, 0, 0, paint);
+ y += paint.getFontMetrics(NULL)*scaleFactor;
+ }
+
+ // check gamma-corrected blending
+ const SkColor fg[] = {
+ 0xFFFFFFFF,
+ 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF,
+ 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
+ 0xFF000000,
+ };
+
+ paint.setColor(0xFFF1F1F1);
+ SkRect r = SkRect::MakeLTRB(690, 250, 840, 460);
+ canvas->drawRect(r, paint);
+
+ x = SkIntToScalar(700);
+ y = SkIntToScalar(270);
+ paint.setTextSize(SkIntToScalar(22));
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) {
+ paint.setColor(fg[i]);
+
+ canvas->drawText(text, textLen, x, y, paint);
+ y += paint.getFontMetrics(NULL);
+ }
+
+ paint.setColor(0xFF1F1F1F);
+ r = SkRect::MakeLTRB(840, 250, 990, 460);
+ canvas->drawRect(r, paint);
+
+ x = SkIntToScalar(850);
+ y = SkIntToScalar(270);
+ paint.setTextSize(SkIntToScalar(22));
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) {
+ paint.setColor(fg[i]);
+
+ canvas->drawText(text, textLen, x, y, paint);
+ y += paint.getFontMetrics(NULL);
+ }
+
+#if SK_SUPPORT_GPU
+ // render offscreen buffer
+ SkImage* image = surface->newImageSnapshot();
+ image->draw(inputCanvas, 0, 0, NULL);
+ image->unref();
+#endif
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new DFTextGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/fontscaler.cpp b/gm/fontscaler.cpp
index 8aef8f0ebe..eb38013cb1 100644
--- a/gm/fontscaler.cpp
+++ b/gm/fontscaler.cpp
@@ -72,12 +72,10 @@ protected:
canvas->drawRect(r, p);
}
- int index = 0;
for (int ps = 6; ps <= 22; ps++) {
paint.setTextSize(SkIntToScalar(ps));
canvas->drawText(text, textLen, x, y, paint);
y += paint.getFontMetrics(NULL);
- index += 1;
}
}
canvas->translate(0, SkIntToScalar(360));
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index f3d7b80a7b..1ee94db929 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -63,6 +63,7 @@
'../gm/dashing.cpp',
'../gm/deviceproperties.cpp',
'../gm/distantclip.cpp',
+ '../gm/dftext.cpp',
'../gm/displacement.cpp',
'../gm/downsamplebitmap.cpp',
'../gm/drawbitmaprect.cpp',
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index d32dcb9c21..18058be17f 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -127,9 +127,9 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo
// set up any flags
uint32_t flags = 0;
- flags |= fContext->getMatrix().isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+ flags |= fTextMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
- flags |= fUseLCDText && fContext->getMatrix().rectStaysRect() ?
+ flags |= fUseLCDText && fTextMatrix.rectStaysRect() ?
kRectToRect_DistanceFieldEffectFlag : 0;
bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
fDeviceProperties.fGeometry.getLayout();
@@ -176,7 +176,8 @@ void GrDistanceFieldTextContext::flushGlyphs() {
GrDrawState* drawState = fDrawTarget->drawState();
GrDrawState::AutoRestoreEffects are(drawState);
- drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
+
+ drawState->setFromPaint(fPaint, fTextMatrix, fContext->getRenderTarget());
if (fCurrVertex > 0) {
// setup our sampler state for our text texture/atlas
@@ -443,18 +444,32 @@ inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint
fStrike = NULL;
+ fTextMatrix = fContext->getMatrix();
+
+ // getMaxScale doesn't support perspective, so neither do we at the moment
+ SkASSERT(!fTextMatrix.hasPerspective());
+ SkScalar maxScale = fTextMatrix.getMaxScale();
+ SkScalar textSize = fSkPaint.getTextSize();
+ // if we have non-unity scale, we need to adjust our text size accordingly
+ // to avoid aliasing, and prescale the matrix by the inverse to end up with the same size
+ // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
+ if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
+ textSize *= maxScale;
+ fTextMatrix.preScale(SK_Scalar1 / maxScale, SK_Scalar1 / maxScale);
+ }
+
fCurrVertex = 0;
fVertices = NULL;
- if (fSkPaint.getTextSize() <= kSmallDFFontLimit) {
- fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize;
+ if (textSize <= kSmallDFFontLimit) {
+ fTextRatio = textSize / kSmallDFFontSize;
fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
- } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) {
- fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize;
+ } else if (textSize <= kMediumDFFontLimit) {
+ fTextRatio = textSize / kMediumDFFontSize;
fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
} else {
- fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize;
+ fTextRatio = textSize / kLargeDFFontSize;
fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
}
diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h
index 75a13b385b..15ff6d9d78 100644
--- a/src/gpu/GrDistanceFieldTextContext.h
+++ b/src/gpu/GrDistanceFieldTextContext.h
@@ -31,6 +31,7 @@ public:
private:
GrTextStrike* fStrike;
+ SkMatrix fTextMatrix;
SkScalar fTextRatio;
bool fUseLCDText;
bool fEnableDFRendering;
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index ee7dd61387..b689c8f6a1 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -34,7 +34,11 @@ public:
GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect& drawEffect)
: INHERITED (factory)
- , fTextureSize(SkISize::Make(-1,-1)) {}
+ , fTextureSize(SkISize::Make(-1,-1))
+#ifdef SK_GAMMA_APPLY_TO_A8
+ , fLuminance(-1.0f)
+#endif
+ {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrDrawEffect& drawEffect,
@@ -262,7 +266,8 @@ public:
GrGLDistanceFieldLCDTextureEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect& drawEffect)
: INHERITED (factory)
- , fTextureSize(SkISize::Make(-1,-1)) {}
+ , fTextureSize(SkISize::Make(-1,-1))
+ , fTextColor(GrColor_ILLEGAL) {}
virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrDrawEffect& drawEffect,