Chromium Code Reviews| 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; |
| } |
| + |