diff --git a/include/gpu/GrFontScaler.h b/include/gpu/GrFontScaler.h index d307cabb42..0132d51304 100644 --- a/include/gpu/GrFontScaler.h +++ b/include/gpu/GrFontScaler.h @@ -29,6 +29,12 @@ public: virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds) = 0; virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height, int rowBytes, void* image) = 0; + // get bounds for distance field associated with packed ID + virtual bool getPackedGlyphDFBounds(GrGlyph::PackedID, SkIRect* bounds) = 0; + // copies distance field bytes into pre-allocated dfImage + // (should be width*height bytes in size) + virtual bool getPackedGlyphDFImage(GrGlyph::PackedID, int width, int height, + void* dfImage) = 0; virtual bool getGlyphPath(uint16_t glyphID, SkPath*) = 0; private: diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h index 6cfa0faedf..2d0418bf08 100644 --- a/include/gpu/SkGr.h +++ b/include/gpu/SkGr.h @@ -83,9 +83,12 @@ public: // overrides virtual const GrKey* getKey(); virtual GrMaskFormat getMaskFormat(); - virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds); + virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds) SK_OVERRIDE; virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height, - int rowBytes, void* image); + int rowBytes, void* image) SK_OVERRIDE; + virtual bool getPackedGlyphDFBounds(GrGlyph::PackedID, SkIRect* bounds) SK_OVERRIDE; + virtual bool getPackedGlyphDFImage(GrGlyph::PackedID, int width, int height, + void* image) SK_OVERRIDE; virtual bool getGlyphPath(uint16_t glyphID, SkPath*); private: diff --git a/src/core/SkDistanceFieldGen.cpp b/src/core/SkDistanceFieldGen.cpp index 8ec7f323ec..aec5f1d13e 100755 --- a/src/core/SkDistanceFieldGen.cpp +++ b/src/core/SkDistanceFieldGen.cpp @@ -327,19 +327,17 @@ static unsigned char pack_distance_field_val(float dist, float distanceMagnitude } #endif -// assumes an 8-bit image and distance field -bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, - const unsigned char* image, - int width, int height, - int distanceMagnitude) { +// assumes a padded 8-bit image and distance field +// width and height are the original width and height of the image +bool generate_distance_field_from_image(unsigned char* distanceField, + const unsigned char* copyPtr, + int width, int height) { SkASSERT(NULL != distanceField); - SkASSERT(NULL != image); + SkASSERT(NULL != copyPtr); - // the final distance field will have additional texels on each side to handle - // the maximum distance + 1 for bilerp // we expand our temp data by one more on each side to simplify // the scanning code -- will always be treated as infinitely far away - int pad = distanceMagnitude+2; + int pad = SK_DistanceFieldPad + 1; // set params for distance field data int dataWidth = width + 2*pad; @@ -355,27 +353,10 @@ bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, unsigned char* edgePtr = (unsigned char*) edgeStorage.get(); sk_bzero(edgePtr, dataWidth*dataHeight*sizeof(char)); - SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char)); - unsigned char* copyPtr = (unsigned char*) copyStorage.get(); - - // we copy our source image into a padded copy to ensure we catch edge transitions - // around the outside - const unsigned char* currImage = image; - sk_bzero(copyPtr, (width+2)*sizeof(char)); - unsigned char* currCopy = copyPtr + width + 2; - for (int i = 0; i < height; ++i) { - *currCopy++ = 0; - memcpy(currCopy, currImage, width*sizeof(char)); - currImage += width; - currCopy += width; - *currCopy++ = 0; - } - sk_bzero(currCopy, (width+2)*sizeof(char)); - // copy glyph into distance field storage init_glyph_data(dataPtr, edgePtr, copyPtr, dataWidth, dataHeight, - width+2, height+2, pad-1); + width+2, height+2, SK_DistanceFieldPad); // create initial distance data, particularly at edges init_distances(dataPtr, edgePtr, dataWidth, dataHeight); @@ -465,7 +446,7 @@ bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, } else { dist = SkScalarSqrt(currData->fDistSq); } - *dfPtr++ = pack_distance_field_val(dist, (float)distanceMagnitude); + *dfPtr++ = pack_distance_field_val(dist, (float)SK_DistanceFieldMagnitude); #endif ++currData; ++currEdge; @@ -476,3 +457,65 @@ bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, return true; } + +// assumes an 8-bit image and distance field +bool SkGenerateDistanceFieldFromA8Image(unsigned char* distanceField, + const unsigned char* image, + int width, int height, int rowBytes) { + SkASSERT(NULL != distanceField); + SkASSERT(NULL != image); + + // create temp data + SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char)); + unsigned char* copyPtr = (unsigned char*) copyStorage.get(); + + // we copy our source image into a padded copy to ensure we catch edge transitions + // around the outside + const unsigned char* currSrcScanLine = image; + sk_bzero(copyPtr, (width+2)*sizeof(char)); + unsigned char* currDestPtr = copyPtr + width + 2; + for (int i = 0; i < height; ++i) { + *currDestPtr++ = 0; + memcpy(currDestPtr, currSrcScanLine, rowBytes); + currSrcScanLine += rowBytes; + currDestPtr += width; + *currDestPtr++ = 0; + } + sk_bzero(currDestPtr, (width+2)*sizeof(char)); + + return generate_distance_field_from_image(distanceField, copyPtr, width, height); +} + +// assumes a 1-bit image and 8-bit distance field +bool SkGenerateDistanceFieldFromBWImage(unsigned char* distanceField, + const unsigned char* image, + int width, int height, int rowBytes) { + SkASSERT(NULL != distanceField); + SkASSERT(NULL != image); + + // create temp data + SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char)); + unsigned char* copyPtr = (unsigned char*) copyStorage.get(); + + // we copy our source image into a padded copy to ensure we catch edge transitions + // around the outside + const unsigned char* currSrcScanLine = image; + sk_bzero(copyPtr, (width+2)*sizeof(char)); + unsigned char* currDestPtr = copyPtr + width + 2; + for (int i = 0; i < height; ++i) { + *currDestPtr++ = 0; + int rowWritesLeft = width; + const unsigned char *maskPtr = currSrcScanLine; + while (rowWritesLeft > 0) { + unsigned mask = *maskPtr++; + for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { + *currDestPtr++ = (mask & (1 << i)) ? 0xff : 0; + } + } + currSrcScanLine += rowBytes; + *currDestPtr++ = 0; + } + sk_bzero(currDestPtr, (width+2)*sizeof(char)); + + return generate_distance_field_from_image(distanceField, copyPtr, width, height); +} diff --git a/src/core/SkDistanceFieldGen.h b/src/core/SkDistanceFieldGen.h index 3d2ec23b75..756cff14a3 100644 --- a/src/core/SkDistanceFieldGen.h +++ b/src/core/SkDistanceFieldGen.h @@ -7,19 +7,54 @@ #ifndef SkDistanceFieldGen_DEFINED #define SkDistanceFieldGen_DEFINED +#include "SkTypes.h" + +// the max magnitude for the distance field +// distance values are limited to the range [-SK_DistanceFieldMagnitude, SK_DistanceFieldMagnitude) +#define SK_DistanceFieldMagnitude 4 +// we need to pad around the original glyph to allow our maximum distance of +// SK_DistanceFieldMagnitude texels away from any edge +// we add one to this pad to allow for bilerp +#define SK_DistanceFieldPad (SK_DistanceFieldMagnitude+1) + +// for the fragment shader +// 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 SK_DistanceFieldMultiplier "7.96875" +#define SK_DistanceFieldThreshold "0.50196078431" + /** Given 8-bit mask data, generate the associated distance field * @param distanceField The distance field to be generated. Should already be allocated - * by the client with the padding below. + * by the client with the padding above. * @param image 8-bit mask we're using to generate the distance field. - * @param w Width of the image. - * @param h Height of the image. - * @param distanceMagnitude Largest possible absolute value for the distance. The distance field - * will be padded to w + 2*distanceMagnitude, h + 2*distanceMagnitude. + * @param w Width of the original image. + * @param h Height of the original image. + * @param rowBytes Size of each row in the image, in bytes */ -bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, - const unsigned char* image, - int w, int h, - int distanceMagnitude); +bool SkGenerateDistanceFieldFromA8Image(unsigned char* distanceField, + const unsigned char* image, + int w, int h, int rowBytes); + +/** Given 1-bit mask data, generate the associated distance field + + * @param distanceField The distance field to be generated. Should already be allocated + * by the client with the padding above. + * @param image 1-bit mask we're using to generate the distance field. + * @param w Width of the original image. + * @param h Height of the original image. + * @param rowBytes Size of each row in the image, in bytes + */ +bool SkGenerateDistanceFieldFromBWImage(unsigned char* distanceField, + const unsigned char* image, + int w, int h, int rowBytes); + +/** Given width and height of original image, return size (in bytes) of distance field + * @param w Width of the original image. + * @param h Height of the original image. + */ +inline size_t SkComputeDistanceFieldSize(int w, int h) { + return (w + 2*SK_DistanceFieldPad) * (h + 2*SK_DistanceFieldPad) * sizeof(unsigned char); +} #endif diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h index 649fa7dd5d..73afb132d6 100644 --- a/src/core/SkGlyph.h +++ b/src/core/SkGlyph.h @@ -29,6 +29,7 @@ struct SkGlyph { uint16_t fWidth, fHeight; int16_t fTop, fLeft; + void* fDistanceField; uint8_t fMaskFormat; int8_t fRsbDelta, fLsbDelta; // used by auto-kerning @@ -36,6 +37,7 @@ struct SkGlyph { fID = id; fImage = NULL; fPath = NULL; + fDistanceField = NULL; fMaskFormat = MASK_FORMAT_UNKNOWN; } diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp old mode 100644 new mode 100755 index 2b1b62b839..7b57e2f55a --- a/src/core/SkGlyphCache.cpp +++ b/src/core/SkGlyphCache.cpp @@ -9,6 +9,7 @@ #include "SkGlyphCache.h" #include "SkGlyphCache_Globals.h" +#include "SkDistanceFieldGen.h" #include "SkGraphics.h" #include "SkPaint.h" #include "SkPath.h" @@ -328,12 +329,12 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { const void* SkGlyphCache::findImage(const SkGlyph& glyph) { if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { - if (glyph.fImage == NULL) { + if (NULL == glyph.fImage) { size_t size = glyph.computeImageSize(); const_cast(glyph).fImage = fGlyphAlloc.alloc(size, SkChunkAlloc::kReturnNil_AllocFailType); // check that alloc() actually succeeded - if (glyph.fImage) { + if (NULL != glyph.fImage) { fScalerContext->getImage(glyph); // TODO: the scaler may have changed the maskformat during // getImage (e.g. from AA or LCD to BW) which means we may have @@ -358,6 +359,45 @@ const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { return glyph.fPath; } +const void* SkGlyphCache::findDistanceField(const SkGlyph& glyph) { + if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { + if (NULL == glyph.fDistanceField) { + size_t size = SkComputeDistanceFieldSize(glyph.fWidth, glyph.fHeight); + if (size == 0) { + return NULL; + } + const void* image = this->findImage(glyph); + // now generate the distance field + if (NULL != image) { + const_cast(glyph).fDistanceField = fGlyphAlloc.alloc(size, + SkChunkAlloc::kReturnNil_AllocFailType); + if (NULL != glyph.fDistanceField) { + SkMask::Format maskFormat = static_cast(glyph.fMaskFormat); + if (SkMask::kA8_Format == maskFormat) { + // make the distance field from the image + SkGenerateDistanceFieldFromA8Image((unsigned char*)glyph.fDistanceField, + (unsigned char*)glyph.fImage, + glyph.fWidth, glyph.fHeight, + glyph.rowBytes()); + fMemoryUsed += size; + } else if (SkMask::kBW_Format == maskFormat) { + // make the distance field from the image + SkGenerateDistanceFieldFromBWImage((unsigned char*)glyph.fDistanceField, + (unsigned char*)glyph.fImage, + glyph.fWidth, glyph.fHeight, + glyph.rowBytes()); + fMemoryUsed += size; + } else { + fGlyphAlloc.unalloc(glyph.fDistanceField); + const_cast(glyph).fDistanceField = NULL; + } + } + } + } + } + return glyph.fDistanceField; +} + /////////////////////////////////////////////////////////////////////////////// bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { @@ -649,6 +689,9 @@ void SkGlyphCache::validate() const { if (glyph->fImage) { SkASSERT(fGlyphAlloc.contains(glyph->fImage)); } + if (glyph->fDistanceField) { + SkASSERT(fGlyphAlloc.contains(glyph->fDistanceField)); + } } #endif } diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index 135942b28b..8b404dcc09 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -92,6 +92,10 @@ public: this will trigger that. */ const SkPath* findPath(const SkGlyph&); + /** Return the distance field associated with the glyph. If it has not been generated + this will trigger that. + */ + const void* findDistanceField(const SkGlyph&); /** Return the vertical metrics for this strike. */ diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index 568f09563f..448e709805 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -239,10 +239,11 @@ void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed, } 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 65ead0f0bb..29d1b91e8e 100644 --- a/src/gpu/GrTextStrike.cpp +++ b/src/gpu/GrTextStrike.cpp @@ -214,10 +214,6 @@ void GrFontCache::dump() const { 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 @@ GrTextStrike::~GrTextStrike() { 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 @@ bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) { 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 8fdae48a2a..c0be4ff78e 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 @@ const GrKey* SkGrFontScaler::getKey() { 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 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, 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 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, 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 8a023cd1d0..b332c7d2cf 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 @@ public: 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 @@ public: 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.