Move distance field generation to the glyph cache.
Distance fields are currently created in GrTextStrike, which is the wrong place. This moves that to the glyph cache where it belongs.
As part of my testing, I found that when we fall back to paths in the GrDistanceFieldTextContext it was not scaling them properly, so that's fixed in here too.
R=robertphillips@google.com, reed@google.com
Author: jvanverth@google.com
Review URL: https://codereview.chromium.org/227593010
git-svn-id: http://skia.googlecode.com/svn/trunk@14193 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 568f095..448e709 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -239,10 +239,11 @@
}
GrContext::AutoMatrix am;
- SkMatrix translate;
- translate.setTranslate(sx, sy);
+ SkMatrix ctm;
+ ctm.setScale(fTextRatio, fTextRatio);
+ ctm.postTranslate(sx, sy);
GrPaint tmpPaint(fPaint);
- am.setPreConcat(fContext, translate, &tmpPaint);
+ am.setPreConcat(fContext, ctm, &tmpPaint);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
return;
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp
index 65ead0f..29d1b91 100644
--- a/src/gpu/GrTextStrike.cpp
+++ b/src/gpu/GrTextStrike.cpp
@@ -214,10 +214,6 @@
static int gCounter;
#endif
-// this acts as the max magnitude for the distance field,
-// as well as the pad we need around the glyph
-#define DISTANCE_FIELD_RANGE 4
-
/*
The text strike is specific to a given font/style/matrix setup, which is
represented by the GrHostFontScaler object we are given in getGlyph().
@@ -260,20 +256,17 @@
GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
GrFontScaler* scaler) {
SkIRect bounds;
- if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
- return NULL;
+ if (fUseDistanceField) {
+ if (!scaler->getPackedGlyphDFBounds(packed, &bounds)) {
+ return NULL;
+ }
+ } else {
+ if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
+ return NULL;
+ }
}
GrGlyph* glyph = fPool.alloc();
- // expand bounds to hold full distance field data
- // + room for bilerp
- int pad = DISTANCE_FIELD_RANGE+1;
- if (fUseDistanceField) {
- bounds.fLeft -= pad;
- bounds.fRight += pad;
- bounds.fTop -= pad;
- bounds.fBottom += pad;
- }
glyph->init(packed, bounds);
fCache.insert(packed, glyph);
return glyph;
@@ -306,56 +299,27 @@
int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
- GrPlot* plot;
+ size_t size = glyph->fBounds.area() * bytesPerPixel;
+ SkAutoSMalloc<1024> storage(size);
if (fUseDistanceField) {
- // we've already expanded the glyph dimensions to match the final size
- // but must shrink back down to get the packed glyph data
- int dfWidth = glyph->width();
- int dfHeight = glyph->height();
- int pad = DISTANCE_FIELD_RANGE+1;
- int width = dfWidth - 2*pad;
- int height = dfHeight - 2*pad;
- int stride = width*bytesPerPixel;
-
- size_t size = width * height * bytesPerPixel;
- SkAutoSMalloc<1024> storage(size);
- if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride, storage.get())) {
+ if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(),
+ glyph->height(),
+ storage.get())) {
return false;
}
-
- // alloc storage for distance field glyph
- size_t dfSize = dfWidth * dfHeight * bytesPerPixel;
- SkAutoSMalloc<1024> dfStorage(dfSize);
-
- if (1 == bytesPerPixel) {
- (void) SkGenerateDistanceFieldFromImage((unsigned char*)dfStorage.get(),
- (unsigned char*)storage.get(),
- width, height, DISTANCE_FIELD_RANGE);
- } else {
- // distance fields should only be used to represent alpha masks
- SkASSERT(false);
- return false;
- }
-
- // copy to atlas
- plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get(),
- &glyph->fAtlasLocation);
-
} else {
- size_t size = glyph->fBounds.area() * bytesPerPixel;
- SkAutoSMalloc<1024> storage(size);
if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
glyph->height(),
glyph->width() * bytesPerPixel,
storage.get())) {
return false;
}
-
- plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
- glyph->height(), storage.get(),
- &glyph->fAtlasLocation);
}
+ GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
+ glyph->height(), storage.get(),
+ &glyph->fAtlasLocation);
+
if (NULL == plot) {
return false;
}
diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp
index 8fdae48..c0be4ff 100644
--- a/src/gpu/SkGrFontScaler.cpp
+++ b/src/gpu/SkGrFontScaler.cpp
@@ -10,6 +10,7 @@
#include "GrTemplates.h"
#include "SkGr.h"
#include "SkDescriptor.h"
+#include "SkDistanceFieldGen.h"
#include "SkGlyphCache.h"
class SkGrDescKey : public GrKey {
@@ -102,14 +103,23 @@
return fKey;
}
-bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed,
- SkIRect* bounds) {
+bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
- GrGlyph::UnpackFixedX(packed),
- GrGlyph::UnpackFixedY(packed));
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
- return true;
+ return true;
+}
+
+bool SkGrFontScaler::getPackedGlyphDFBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
+ const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
+ bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
+ bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
+
+ return true;
}
namespace {
@@ -142,8 +152,8 @@
int width, int height,
int dstRB, void* dst) {
const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
- GrGlyph::UnpackFixedX(packed),
- GrGlyph::UnpackFixedY(packed));
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
SkASSERT(glyph.fWidth == width);
SkASSERT(glyph.fHeight == height);
const void* src = fStrike->findImage(glyph);
@@ -190,6 +200,24 @@
return true;
}
+bool SkGrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
+ int width, int height,
+ void* dst) {
+ const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
+ SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
+ SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
+ const void* src = fStrike->findDistanceField(glyph);
+ if (NULL == src) {
+ return false;
+ }
+
+ memcpy(dst, src, width * height);
+
+ return true;
+}
+
// we should just return const SkPath* (NULL means false)
bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 8a023cd..b332c7d 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -13,10 +13,7 @@
#include "GrTBackendEffectFactory.h"
#include "GrTexture.h"
-// The distance field is constructed as unsigned char values, so that the zero value is at 128,
-// and the range is [-4, 4 - 1/255). Hence our multiplier is 8 - 1/32 and zero threshold is 128/255.
-#define MULTIPLIER "7.96875"
-#define THRESHOLD "0.50196078431"
+#include "SkDistanceFieldGen.h"
class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect {
public:
@@ -58,7 +55,8 @@
fsCoordName.c_str(),
kVec2f_GrSLType);
builder->fsCodeAppend(";\n");
- builder->fsCodeAppend("\tfloat distance = " MULTIPLIER "*(texColor.r - " THRESHOLD ");\n");
+ builder->fsCodeAppend("\tfloat distance = "
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n");
// 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
@@ -239,20 +237,22 @@
builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType);
builder->fsCodeAppend(";\n");
builder->fsCodeAppend("\tvec3 distance;\n");
- builder->fsCodeAppend("\tdistance.y = " MULTIPLIER "*(texColor.r - " THRESHOLD ");\n");
+ builder->fsCodeAppend("\tdistance.y = "
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n");
// red is distance to left offset
builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n");
builder->fsCodeAppend("\ttexColor = ");
builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
builder->fsCodeAppend(";\n");
- builder->fsCodeAppend("\tdistance.x = " MULTIPLIER "*(texColor.r - " THRESHOLD ");\n");
+ builder->fsCodeAppend("\tdistance.x = "
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n");
// blue is distance to right offset
builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n");
builder->fsCodeAppend("\ttexColor = ");
builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
builder->fsCodeAppend(";\n");
- builder->fsCodeAppend("\tdistance.z = " MULTIPLIER "*(texColor.r - " THRESHOLD ");\n");
-
+ builder->fsCodeAppend("\tdistance.z = "
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ");\n");
// 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.