Index: src/gpu/GrTextStrike.cpp |
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp |
index a96aab16c8f640f18905d82766590b9104c55563..c62d8c1ae34d266fbb801af6625f3e56b62684cc 100644 |
--- a/src/gpu/GrTextStrike.cpp |
+++ b/src/gpu/GrTextStrike.cpp |
@@ -12,6 +12,10 @@ |
#include "GrTextStrike_impl.h" |
#include "SkString.h" |
+#if GR_DISTANCEFIELD_FONTS |
+#include "edtaa3.h" |
+#endif |
+ |
SK_DEFINE_INST_COUNT(GrFontScaler) |
SK_DEFINE_INST_COUNT(GrKey) |
@@ -193,6 +197,11 @@ void GrFontCache::dump() const { |
static int gCounter; |
#endif |
+#if GR_DISTANCEFIELD_FONTS |
+#define DISTANCE_FIELD_PAD 4 |
+#define DISTANCE_FIELD_RANGE (4.0) |
+#endif |
+ |
/* |
The text strike is specific to a given font/style/matrix setup, which is |
represented by the GrHostFontScaler object we are given in getGlyph(). |
@@ -246,6 +255,15 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, |
} |
GrGlyph* glyph = fPool.alloc(); |
+#if GR_DISTANCEFIELD_FONTS |
+ // expand bounds to hold full distance field data |
+ if (fUseDistanceField) { |
+ bounds.fLeft -= DISTANCE_FIELD_PAD; |
+ bounds.fRight += DISTANCE_FIELD_PAD; |
+ bounds.fTop -= DISTANCE_FIELD_PAD; |
+ bounds.fBottom += DISTANCE_FIELD_PAD; |
+ } |
+#endif |
glyph->init(packed, bounds); |
fCache.insert(packed, glyph); |
return glyph; |
@@ -256,6 +274,7 @@ bool GrTextStrike::removeUnusedPlots() { |
return fAtlasMgr->removeUnusedPlots(&fAtlas); |
} |
+ |
bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
#if 0 // testing hack to force us to flush our cache often |
static int gCounter; |
@@ -270,18 +289,109 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
SkAutoRef ar(scaler); |
int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); |
- 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; |
+ |
+ GrPlot* plot; |
+#if GR_DISTANCEFIELD_FONTS |
+ if (fUseDistanceField) { |
+ SkASSERT(1 == bytesPerPixel); |
+ |
+ // we've already expanded the glyph dimensions to match the final size |
+ // but must shrink back down to get the packed glyph data |
robertphillips
2013/11/05 15:30:26
dfWidth/dfHeight?
jvanverth1
2013/11/05 17:09:22
Done.
|
+ int dfwidth = glyph->width(); |
+ int dfheight = glyph->height(); |
+ int width = dfwidth - 2*DISTANCE_FIELD_PAD; |
+ int height = dfheight - 2*DISTANCE_FIELD_PAD; |
+ size_t stride = width*bytesPerPixel; |
+ |
+ size_t size = width * height * bytesPerPixel; |
+ SkAutoSMalloc<1024> storage(size); |
+ if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride, storage.get())) { |
+ return false; |
+ } |
+ |
+ // alloc storage for distance field glyph |
robertphillips
2013/11/05 15:30:26
dfSize?
jvanverth1
2013/11/05 17:09:22
Done.
|
+ size_t dfsize = dfwidth * dfheight * bytesPerPixel; |
+ SkAutoSMalloc<1024> dfstorage(dfsize); |
+ |
+ // copy glyph into distance field storage |
+ memset(dfstorage.get(), 0, dfsize); |
bsalomon
2013/11/05 15:28:52
not a blocker, but there is an sk_bzero, not sure
jvanverth1
2013/11/05 17:09:22
Done.
|
+ |
+ unsigned char* ptr = (unsigned char*) storage.get(); |
robertphillips
2013/11/05 15:30:26
dfPtr?
jvanverth1
2013/11/05 17:09:22
Done.
|
+ unsigned char* dfptr = (unsigned char*) dfstorage.get(); |
+ size_t dfstride = dfwidth*bytesPerPixel; |
+ dfptr += DISTANCE_FIELD_PAD*dfstride; |
+ dfptr += DISTANCE_FIELD_PAD*bytesPerPixel; |
+ |
+ for (int i = 0; i < height; ++i) { |
+ memcpy(dfptr, ptr, stride); |
+ |
+ dfptr += dfstride; |
+ ptr += stride; |
+ } |
+ |
+ // generate distance field data |
robertphillips
2013/11/05 15:30:26
distX\distY? outerDist?
some form of SkNEW?
some s
jvanverth1
2013/11/05 17:09:22
Done.
|
+ short* distx = new short[dfwidth*dfheight]; |
bsalomon
2013/11/05 15:28:52
SkNEW(), SkDELETE()
jvanverth1
2013/11/05 17:09:22
Done.
|
+ short* disty = new short[dfwidth*dfheight]; |
+ double* outerdist = new double[dfwidth*dfheight]; |
+ double* gx = new double[dfwidth*dfheight]; |
+ double* gy = new double[dfwidth*dfheight]; |
+ dfptr = (unsigned char*) dfstorage.get(); |
robertphillips
2013/11/05 15:30:26
is it possible to namespace these guys to make it
|
+ computegradient(dfptr, dfwidth, dfheight, gx, gy); |
+ edtaa3(dfptr, gx, gy, dfwidth, dfheight, distx, disty, outerdist); |
+ |
+ for (int i = 0; i < dfwidth*dfheight; ++i) { |
+ *dfptr++ = 255 - *dfptr; |
+ } |
+ double* innerdist = new double[dfwidth*dfheight]; |
+ dfptr = (unsigned char*) dfstorage.get(); |
+ memset(gx, 0, sizeof(double)*dfwidth*dfheight); |
+ memset(gy, 0, sizeof(double)*dfwidth*dfheight); |
+ computegradient(dfptr, dfwidth, dfheight, gx, gy); |
+ edtaa3(dfptr, gx, gy, dfwidth, dfheight, distx, disty, innerdist); |
+ |
+ for (int i = 0; i < dfwidth*dfheight; ++i) { |
+ unsigned char val; |
+ double outerval = outerdist[i]; |
robertphillips
2013/11/05 15:30:26
newlines on {}s?
jvanverth1
2013/11/05 17:09:22
Done.
|
+ if (outerval < 0.0) { outerval = 0.0; } |
+ double innerval = innerdist[i]; |
+ if (innerval < 0.0) { innerval = 0.0; } |
+ double dist = outerval - innerval; |
+ if (dist <= -DISTANCE_FIELD_RANGE) { |
+ val = 255; |
+ } else if (dist > DISTANCE_FIELD_RANGE) { |
+ val = 0; |
+ } else { |
+ val = (unsigned char)((DISTANCE_FIELD_RANGE-dist)*128.0/DISTANCE_FIELD_RANGE); |
+ } |
+ *dfptr++ = val; |
+ } |
+ |
+ delete [] distx; |
+ delete [] disty; |
+ delete [] innerdist; |
+ delete [] outerdist; |
+ |
+ // copy to atlas |
+ plot = fAtlasMgr->addToAtlas(&fAtlas, dfwidth, dfheight, dfstorage.get(), |
robertphillips
2013/11/05 15:30:26
indent?
jvanverth1
2013/11/05 17:09:22
Done.
|
+ &glyph->fAtlasLocation); |
+ |
+ } else { |
+#endif |
+ 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(), |
robertphillips
2013/11/05 15:30:26
indent?
jvanverth1
2013/11/05 17:09:22
Done.
|
+ &glyph->fAtlasLocation); |
+#if GR_DISTANCEFIELD_FONTS |
} |
+#endif |
- GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), |
- glyph->height(), storage.get(), |
- &glyph->fAtlasLocation); |
if (NULL == plot) { |
return false; |
} |
@@ -289,3 +399,4 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
glyph->fPlot = plot; |
return true; |
} |
+ |