| Index: src/gpu/GrDistanceFieldTextContext.cpp | 
| diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp | 
| deleted file mode 100755 | 
| index a5d11e6fb9fbc4afc5f1dcf653e90672b9ff41db..0000000000000000000000000000000000000000 | 
| --- a/src/gpu/GrDistanceFieldTextContext.cpp | 
| +++ /dev/null | 
| @@ -1,804 +0,0 @@ | 
| -/* | 
| - * Copyright 2013 Google Inc. | 
| - * | 
| - * Use of this source code is governed by a BSD-style license that can be | 
| - * found in the LICENSE file. | 
| - */ | 
| - | 
| -#include "GrDistanceFieldTextContext.h" | 
| -#include "GrAtlas.h" | 
| -#include "GrAtlasTextContext.h" | 
| -#include "GrBitmapTextContext.h" | 
| -#include "GrDrawTarget.h" | 
| -#include "GrDrawTargetCaps.h" | 
| -#include "GrFontAtlasSizes.h" | 
| -#include "GrFontCache.h" | 
| -#include "GrFontScaler.h" | 
| -#include "GrGpu.h" | 
| -#include "GrIndexBuffer.h" | 
| -#include "GrStrokeInfo.h" | 
| -#include "GrTexturePriv.h" | 
| - | 
| -#include "SkAutoKern.h" | 
| -#include "SkColorFilter.h" | 
| -#include "SkDistanceFieldGen.h" | 
| -#include "SkDraw.h" | 
| -#include "SkGlyphCache.h" | 
| -#include "SkGpuDevice.h" | 
| -#include "SkPath.h" | 
| -#include "SkRTConf.h" | 
| -#include "SkStrokeRec.h" | 
| -#include "effects/GrDistanceFieldGeoProc.h" | 
| - | 
| -SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, | 
| -                "Dump the contents of the font cache before every purge."); | 
| - | 
| -static const int kMinDFFontSize = 18; | 
| -static const int kSmallDFFontSize = 32; | 
| -static const int kSmallDFFontLimit = 32; | 
| -static const int kMediumDFFontSize = 72; | 
| -static const int kMediumDFFontLimit = 72; | 
| -static const int kLargeDFFontSize = 162; | 
| - | 
| -static const int kVerticesPerGlyph = 4; | 
| -static const int kIndicesPerGlyph = 6; | 
| - | 
| -#ifdef SK_DEBUG | 
| -static const int kExpectedDistanceAdjustTableSize = 8; | 
| -#endif | 
| -static const int kDistanceAdjustLumShift = 5; | 
| - | 
| -GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, | 
| -                                                       SkGpuDevice* gpuDevice, | 
| -                                                       const SkDeviceProperties& properties, | 
| -                                                       bool enable) | 
| -    : GrTextContext(context, gpuDevice, properties) { | 
| -#if SK_FORCE_DISTANCE_FIELD_TEXT | 
| -    fEnableDFRendering = true; | 
| -#else | 
| -    fEnableDFRendering = enable; | 
| -#endif | 
| -    fStrike = NULL; | 
| -    fDistanceAdjustTable = NULL; | 
| - | 
| -    fEffectTextureUniqueID = SK_InvalidUniqueID; | 
| -    fEffectColor = GrColor_ILLEGAL; | 
| -    fEffectFlags = kInvalid_DistanceFieldEffectFlag; | 
| - | 
| -    fVertices = NULL; | 
| -    fCurrVertex = 0; | 
| -    fAllocVertexCount = 0; | 
| -    fTotalVertexCount = 0; | 
| -    fCurrTexture = NULL; | 
| - | 
| -    fVertexBounds.setLargestInverted(); | 
| -} | 
| - | 
| -GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* context, | 
| -                                                               SkGpuDevice* gpuDevice, | 
| -                                                               const SkDeviceProperties& props, | 
| -                                                               bool enable) { | 
| -    GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextContext, | 
| -                                                         (context, gpuDevice, props, enable)); | 
| -    textContext->buildDistanceAdjustTable(); | 
| -#ifdef USE_BITMAP_TEXTBLOBS | 
| -    textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, gpuDevice, props, | 
| -                                                                   enable); | 
| -#else | 
| -    textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpuDevice, props); | 
| -#endif | 
| - | 
| -    return textContext; | 
| -} | 
| - | 
| -void GrDistanceFieldTextContext::buildDistanceAdjustTable() { | 
| - | 
| -    // This is used for an approximation of the mask gamma hack, used by raster and bitmap | 
| -    // text. The mask gamma hack is based off of guessing what the blend color is going to | 
| -    // be, and adjusting the mask so that when run through the linear blend will | 
| -    // produce the value closest to the desired result. However, in practice this means | 
| -    // that the 'adjusted' mask is just increasing or decreasing the coverage of | 
| -    // the mask depending on what it is thought it will blit against. For black (on | 
| -    // assumed white) this means that coverages are decreased (on a curve). For white (on | 
| -    // assumed black) this means that coverages are increased (on a a curve). At | 
| -    // middle (perceptual) gray (which could be blit against anything) the coverages | 
| -    // remain the same. | 
| -    // | 
| -    // The idea here is that instead of determining the initial (real) coverage and | 
| -    // then adjusting that coverage, we determine an adjusted coverage directly by | 
| -    // essentially manipulating the geometry (in this case, the distance to the glyph | 
| -    // edge). So for black (on assumed white) this thins a bit; for white (on | 
| -    // assumed black) this fake bolds the geometry a bit. | 
| -    // | 
| -    // The distance adjustment is calculated by determining the actual coverage value which | 
| -    // when fed into in the mask gamma table gives us an 'adjusted coverage' value of 0.5. This | 
| -    // actual coverage value (assuming it's between 0 and 1) corresponds to a distance from the | 
| -    // actual edge. So by subtracting this distance adjustment and computing without the | 
| -    // the coverage adjustment we should get 0.5 coverage at the same point. | 
| -    // | 
| -    // This has several implications: | 
| -    //     For non-gray lcd smoothed text, each subpixel essentially is using a | 
| -    //     slightly different geometry. | 
| -    // | 
| -    //     For black (on assumed white) this may not cover some pixels which were | 
| -    //     previously covered; however those pixels would have been only slightly | 
| -    //     covered and that slight coverage would have been decreased anyway. Also, some pixels | 
| -    //     which were previously fully covered may no longer be fully covered. | 
| -    // | 
| -    //     For white (on assumed black) this may cover some pixels which weren't | 
| -    //     previously covered at all. | 
| - | 
| -    int width, height; | 
| -    size_t size; | 
| - | 
| -#ifdef SK_GAMMA_CONTRAST | 
| -    SkScalar contrast = SK_GAMMA_CONTRAST; | 
| -#else | 
| -    SkScalar contrast = 0.5f; | 
| -#endif | 
| -    SkScalar paintGamma = fDeviceProperties.gamma(); | 
| -    SkScalar deviceGamma = fDeviceProperties.gamma(); | 
| - | 
| -    size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma, | 
| -        &width, &height); | 
| - | 
| -    SkASSERT(kExpectedDistanceAdjustTableSize == height); | 
| -    fDistanceAdjustTable = SkNEW_ARRAY(SkScalar, height); | 
| - | 
| -    SkAutoTArray<uint8_t> data((int)size); | 
| -    SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get()); | 
| - | 
| -    // find the inverse points where we cross 0.5 | 
| -    // binsearch might be better, but we only need to do this once on creation | 
| -    for (int row = 0; row < height; ++row) { | 
| -        uint8_t* rowPtr = data.get() + row*width; | 
| -        for (int col = 0; col < width - 1; ++col) { | 
| -            if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) { | 
| -                // compute point where a mask value will give us a result of 0.5 | 
| -                float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPtr[col]); | 
| -                float borderAlpha = (col + interp) / 255.f; | 
| - | 
| -                // compute t value for that alpha | 
| -                // this is an approximate inverse for smoothstep() | 
| -                float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5.0f) / 3.0f; | 
| - | 
| -                // compute distance which gives us that t value | 
| -                const float kDistanceFieldAAFactor = 0.65f; // should match SK_DistanceFieldAAFactor | 
| -                float d = 2.0f*kDistanceFieldAAFactor*t - kDistanceFieldAAFactor; | 
| - | 
| -                fDistanceAdjustTable[row] = d; | 
| -                break; | 
| -            } | 
| -        } | 
| -    } | 
| -} | 
| - | 
| - | 
| -GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { | 
| -    SkDELETE_ARRAY(fDistanceAdjustTable); | 
| -    fDistanceAdjustTable = NULL; | 
| -} | 
| - | 
| -bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt, | 
| -                                         const GrClip& clip, | 
| -                                         const GrPaint& paint, | 
| -                                         const SkPaint& skPaint, | 
| -                                         const SkMatrix& viewMatrix) { | 
| -    // TODO: support perspective (need getMaxScale replacement) | 
| -    if (viewMatrix.hasPerspective()) { | 
| -        return false; | 
| -    } | 
| - | 
| -    SkScalar maxScale = viewMatrix.getMaxScale(); | 
| -    SkScalar scaledTextSize = maxScale*skPaint.getTextSize(); | 
| -    // Hinted text looks far better at small resolutions | 
| -    // Scaling up beyond 2x yields undesireable artifacts | 
| -    if (scaledTextSize < kMinDFFontSize || scaledTextSize > 2*kLargeDFFontSize) { | 
| -        return false; | 
| -    } | 
| - | 
| -    if (!fEnableDFRendering && !skPaint.isDistanceFieldTextTEMP() && | 
| -        scaledTextSize < kLargeDFFontSize) { | 
| -        return false; | 
| -    } | 
| - | 
| -    // rasterizers and mask filters modify alpha, which doesn't | 
| -    // translate well to distance | 
| -    if (skPaint.getRasterizer() || skPaint.getMaskFilter() || | 
| -        !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) { | 
| -        return false; | 
| -    } | 
| - | 
| -    // TODO: add some stroking support | 
| -    if (skPaint.getStyle() != SkPaint::kFill_Style) { | 
| -        return false; | 
| -    } | 
| - | 
| -    return true; | 
| -} | 
| - | 
| -inline void GrDistanceFieldTextContext::init(GrRenderTarget* rt, const GrClip& clip, | 
| -                                             const GrPaint& paint, const SkPaint& skPaint, | 
| -                                             const SkIRect& regionClipBounds) { | 
| -    GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds); | 
| - | 
| -    fStrike = NULL; | 
| - | 
| -    const SkMatrix& ctm = fViewMatrix; | 
| - | 
| -    // getMaxScale doesn't support perspective, so neither do we at the moment | 
| -    SkASSERT(!ctm.hasPerspective()); | 
| -    SkScalar maxScale = ctm.getMaxScale(); | 
| -    SkScalar textSize = fSkPaint.getTextSize(); | 
| -    SkScalar scaledTextSize = textSize; | 
| -    // if we have non-unity scale, we need to choose our base text size | 
| -    // based on the SkPaint's text size multiplied by the max scale factor | 
| -    // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? | 
| -    if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { | 
| -        scaledTextSize *= maxScale; | 
| -    } | 
| - | 
| -    fVertices = NULL; | 
| -    fCurrVertex = 0; | 
| -    fAllocVertexCount = 0; | 
| -    fTotalVertexCount = 0; | 
| - | 
| -    if (scaledTextSize <= kSmallDFFontLimit) { | 
| -        fTextRatio = textSize / kSmallDFFontSize; | 
| -        fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize)); | 
| -#if DEBUG_TEXT_SIZE | 
| -        fSkPaint.setColor(SkColorSetARGB(0xFF, 0x00, 0x00, 0x7F)); | 
| -        fPaint.setColor(GrColorPackRGBA(0x00, 0x00, 0x7F, 0xFF)); | 
| -#endif | 
| -    } else if (scaledTextSize <= kMediumDFFontLimit) { | 
| -        fTextRatio = textSize / kMediumDFFontSize; | 
| -        fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize)); | 
| -#if DEBUG_TEXT_SIZE | 
| -        fSkPaint.setColor(SkColorSetARGB(0xFF, 0x00, 0x3F, 0x00)); | 
| -        fPaint.setColor(GrColorPackRGBA(0x00, 0x3F, 0x00, 0xFF)); | 
| -#endif | 
| -    } else { | 
| -        fTextRatio = textSize / kLargeDFFontSize; | 
| -        fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize)); | 
| -#if DEBUG_TEXT_SIZE | 
| -        fSkPaint.setColor(SkColorSetARGB(0xFF, 0x7F, 0x00, 0x00)); | 
| -        fPaint.setColor(GrColorPackRGBA(0x7F, 0x00, 0x00, 0xFF)); | 
| -#endif | 
| -    } | 
| - | 
| -    fUseLCDText = fSkPaint.isLCDRenderText(); | 
| - | 
| -    fSkPaint.setLCDRenderText(false); | 
| -    fSkPaint.setAutohinted(false); | 
| -    fSkPaint.setHinting(SkPaint::kNormal_Hinting); | 
| -    fSkPaint.setSubpixelText(true); | 
| -} | 
| - | 
| -void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, | 
| -                                            const GrPaint& paint, | 
| -                                            const SkPaint& skPaint, const SkMatrix& viewMatrix, | 
| -                                            const char text[], size_t byteLength, | 
| -                                            SkScalar x, SkScalar y, | 
| -                                            const SkIRect& regionClipBounds) { | 
| -    SkASSERT(byteLength == 0 || text != NULL); | 
| - | 
| -    // nothing to draw | 
| -    if (text == NULL || byteLength == 0) { | 
| -        return; | 
| -    } | 
| - | 
| -    fViewMatrix = viewMatrix; | 
| -    SkDrawCacheProc          glyphCacheProc = skPaint.getDrawCacheProc(); | 
| -    SkAutoGlyphCache         autoCache(skPaint, &fDeviceProperties, NULL); | 
| -    SkGlyphCache*            cache = autoCache.getCache(); | 
| - | 
| -    SkTArray<SkScalar> positions; | 
| - | 
| -    const char* textPtr = text; | 
| -    SkFixed stopX = 0; | 
| -    SkFixed stopY = 0; | 
| -    SkFixed origin; | 
| -    switch (skPaint.getTextAlign()) { | 
| -        case SkPaint::kRight_Align: origin = SK_Fixed1; break; | 
| -        case SkPaint::kCenter_Align: origin = SK_FixedHalf; break; | 
| -        case SkPaint::kLeft_Align: origin = 0; break; | 
| -        default: SkFAIL("Invalid paint origin"); return; | 
| -    } | 
| - | 
| -    SkAutoKern autokern; | 
| -    const char* stop = text + byteLength; | 
| -    while (textPtr < stop) { | 
| -        // don't need x, y here, since all subpixel variants will have the | 
| -        // same advance | 
| -        const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0); | 
| - | 
| -        SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph); | 
| -        positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width))); | 
| - | 
| -        SkFixed height = glyph.fAdvanceY; | 
| -        positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height))); | 
| - | 
| -        stopX += width; | 
| -        stopY += height; | 
| -    } | 
| -    SkASSERT(textPtr == stop); | 
| - | 
| -    // now adjust starting point depending on alignment | 
| -    SkScalar alignX = SkFixedToScalar(stopX); | 
| -    SkScalar alignY = SkFixedToScalar(stopY); | 
| -    if (skPaint.getTextAlign() == SkPaint::kCenter_Align) { | 
| -        alignX = SkScalarHalf(alignX); | 
| -        alignY = SkScalarHalf(alignY); | 
| -    } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) { | 
| -        alignX = 0; | 
| -        alignY = 0; | 
| -    } | 
| -    x -= alignX; | 
| -    y -= alignY; | 
| -    SkPoint offset = SkPoint::Make(x, y); | 
| - | 
| -    this->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, positions.begin(), | 
| -                        2, offset, regionClipBounds); | 
| -} | 
| - | 
| -void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, | 
| -                                               const GrPaint& paint, | 
| -                                               const SkPaint& skPaint, const SkMatrix& viewMatrix, | 
| -                                               const char text[], size_t byteLength, | 
| -                                               const SkScalar pos[], int scalarsPerPosition, | 
| -                                               const SkPoint& offset, | 
| -                                               const SkIRect& regionClipBounds) { | 
| - | 
| -    SkASSERT(byteLength == 0 || text != NULL); | 
| -    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 
| - | 
| -    // nothing to draw | 
| -    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) { | 
| -        return; | 
| -    } | 
| - | 
| -    fViewMatrix = viewMatrix; | 
| -    this->init(rt, clip, paint, skPaint, regionClipBounds); | 
| - | 
| -    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 
| - | 
| -    SkAutoGlyphCacheNoGamma    autoCache(fSkPaint, &fDeviceProperties, NULL); | 
| -    SkGlyphCache*              cache = autoCache.getCache(); | 
| -    GrFontScaler*              fontScaler = GetGrFontScaler(cache); | 
| - | 
| -    int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); | 
| -    fTotalVertexCount = kVerticesPerGlyph*numGlyphs; | 
| - | 
| -    const char*        stop = text + byteLength; | 
| -    SkTArray<char>     fallbackTxt; | 
| -    SkTArray<SkScalar> fallbackPos; | 
| - | 
| -    if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 
| -        while (text < stop) { | 
| -            const char* lastText = text; | 
| -            // the last 2 parameters are ignored | 
| -            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 
| - | 
| -            if (glyph.fWidth) { | 
| -                SkScalar x = offset.x() + pos[0]; | 
| -                SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); | 
| - | 
| -                if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 
| -                                                     glyph.getSubXFixed(), | 
| -                                                     glyph.getSubYFixed(), | 
| -                                                     GrGlyph::kDistance_MaskStyle), | 
| -                                       x, y, fontScaler)) { | 
| -                    // couldn't append, send to fallback | 
| -                    fallbackTxt.push_back_n(SkToInt(text-lastText), lastText); | 
| -                    fallbackPos.push_back(pos[0]); | 
| -                    if (2 == scalarsPerPosition) { | 
| -                        fallbackPos.push_back(pos[1]); | 
| -                    } | 
| -                } | 
| -            } | 
| -            pos += scalarsPerPosition; | 
| -        } | 
| -    } else { | 
| -        SkScalar alignMul = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? SK_ScalarHalf | 
| -                                                                              : SK_Scalar1; | 
| -        while (text < stop) { | 
| -            const char* lastText = text; | 
| -            // the last 2 parameters are ignored | 
| -            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 
| - | 
| -            if (glyph.fWidth) { | 
| -                SkScalar x = offset.x() + pos[0]; | 
| -                SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); | 
| - | 
| -                SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX)*alignMul*fTextRatio; | 
| -                SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY)*alignMul*fTextRatio; | 
| - | 
| -                if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 
| -                                                     glyph.getSubXFixed(), | 
| -                                                     glyph.getSubYFixed(), | 
| -                                                     GrGlyph::kDistance_MaskStyle), | 
| -                                       x - advanceX, y - advanceY, fontScaler)) { | 
| -                    // couldn't append, send to fallback | 
| -                    fallbackTxt.push_back_n(SkToInt(text-lastText), lastText); | 
| -                    fallbackPos.push_back(pos[0]); | 
| -                    if (2 == scalarsPerPosition) { | 
| -                        fallbackPos.push_back(pos[1]); | 
| -                    } | 
| -                } | 
| -            } | 
| -            pos += scalarsPerPosition; | 
| -        } | 
| -    } | 
| - | 
| -    this->finish(); | 
| - | 
| -    if (fallbackTxt.count() > 0) { | 
| -        fFallbackTextContext->drawPosText(rt, clip, paint, skPaint, viewMatrix, | 
| -                                          fallbackTxt.begin(), fallbackTxt.count(), | 
| -                                          fallbackPos.begin(), scalarsPerPosition, offset, | 
| -                                          regionClipBounds); | 
| -    } | 
| -} | 
| - | 
| -static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { | 
| -    unsigned r = SkColorGetR(c); | 
| -    unsigned g = SkColorGetG(c); | 
| -    unsigned b = SkColorGetB(c); | 
| -    return GrColorPackRGBA(r, g, b, 0xff); | 
| -} | 
| - | 
| -static size_t get_vertex_stride(bool useColorVerts) { | 
| -    return useColorVerts ? (sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16)) : | 
| -                           (sizeof(SkPoint) + sizeof(SkIPoint16)); | 
| -} | 
| - | 
| -static void* alloc_vertices(GrDrawTarget* drawTarget, | 
| -                            int numVertices, | 
| -                            bool useColorVerts) { | 
| -    if (numVertices <= 0) { | 
| -        return NULL; | 
| -    } | 
| - | 
| -    void* vertices = NULL; | 
| -    bool success = drawTarget->reserveVertexAndIndexSpace(numVertices, | 
| -                                                          get_vertex_stride(useColorVerts), | 
| -                                                          0, | 
| -                                                          &vertices, | 
| -                                                          NULL); | 
| -    GrAlwaysAssert(success); | 
| -    return vertices; | 
| -} | 
| - | 
| -void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) { | 
| -    GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); | 
| -    GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode); | 
| - | 
| -    uint32_t textureUniqueID = fCurrTexture->getUniqueID(); | 
| -    const SkMatrix& ctm = fViewMatrix; | 
| - | 
| -    // set up any flags | 
| -    uint32_t flags = 0; | 
| -    flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; | 
| -    flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0; | 
| -    flags |= fUseLCDText && ctm.rectStaysRect() ? | 
| -    kRectToRect_DistanceFieldEffectFlag : 0; | 
| -    bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry()); | 
| -    flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; | 
| - | 
| -    // see if we need to create a new effect | 
| -    if (textureUniqueID != fEffectTextureUniqueID || | 
| -        filteredColor != fEffectColor || | 
| -        flags != fEffectFlags || | 
| -        !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) { | 
| -        GrColor color = fPaint.getColor(); | 
| - | 
| -        if (fUseLCDText) { | 
| -            GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); | 
| - | 
| -            float redCorrection = | 
| -                fDistanceAdjustTable[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift]; | 
| -            float greenCorrection = | 
| -                fDistanceAdjustTable[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift]; | 
| -            float blueCorrection = | 
| -                fDistanceAdjustTable[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift]; | 
| -            GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust = | 
| -                GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrection, | 
| -                                                                    greenCorrection, | 
| -                                                                    blueCorrection); | 
| -            fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextGeoProc::Create(color, | 
| -                                                                                 fViewMatrix, | 
| -                                                                                 fCurrTexture, | 
| -                                                                                 params, | 
| -                                                                                 widthAdjust, | 
| -                                                                                 flags)); | 
| -        } else { | 
| -            flags |= kColorAttr_DistanceFieldEffectFlag; | 
| -            bool opaque = GrColorIsOpaque(color); | 
| -#ifdef SK_GAMMA_APPLY_TO_A8 | 
| -            U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.gamma(), | 
| -                                                                filteredColor); | 
| -            float correction = fDistanceAdjustTable[lum >> kDistanceAdjustLumShift]; | 
| -            fCachedGeometryProcessor.reset(GrDistanceFieldA8TextGeoProc::Create(color, | 
| -                                                                                fViewMatrix, | 
| -                                                                                fCurrTexture, | 
| -                                                                                params, | 
| -                                                                                correction, | 
| -                                                                                flags, | 
| -                                                                                opaque)); | 
| -#else | 
| -            fCachedGeometryProcessor.reset(GrDistanceFieldA8TextGeoProc::Create(color, | 
| -                                                                                fViewMatrix, | 
| -                                                                                fCurrTexture, | 
| -                                                                                params, | 
| -                                                                                flags, | 
| -                                                                                opaque)); | 
| -#endif | 
| -        } | 
| -        fEffectTextureUniqueID = textureUniqueID; | 
| -        fEffectColor = filteredColor; | 
| -        fEffectFlags = flags; | 
| -    } | 
| - | 
| -} | 
| - | 
| -inline bool GrDistanceFieldTextContext::uploadGlyph(GrGlyph* glyph, GrFontScaler* scaler) { | 
| -    if (!fStrike->glyphTooLargeForAtlas(glyph)) { | 
| -        if (fStrike->addGlyphToAtlas(glyph, scaler)) { | 
| -            return true; | 
| -        } | 
| - | 
| -        // try to clear out an unused plot before we flush | 
| -        if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) && | 
| -            fStrike->addGlyphToAtlas(glyph, scaler)) { | 
| -            return true; | 
| -        } | 
| - | 
| -        if (c_DumpFontCache) { | 
| -#ifdef SK_DEVELOPER | 
| -            fContext->getFontCache()->dump(); | 
| -#endif | 
| -        } | 
| - | 
| -        // before we purge the cache, we must flush any accumulated draws | 
| -        this->flush(); | 
| -        fContext->flush(); | 
| - | 
| -        // we should have an unused plot now | 
| -        if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) && | 
| -            fStrike->addGlyphToAtlas(glyph, scaler)) { | 
| -            return true; | 
| -        } | 
| - | 
| -        // we should never get here | 
| -        SkASSERT(false); | 
| -    } | 
| - | 
| -    return false; | 
| -} | 
| - | 
| - | 
| -// Returns true if this method handled the glyph, false if needs to be passed to fallback | 
| -// | 
| -bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, | 
| -                                             SkScalar sx, SkScalar sy, | 
| -                                             GrFontScaler* scaler) { | 
| -    if (NULL == fDrawTarget) { | 
| -        return true; | 
| -    } | 
| - | 
| -    if (NULL == fStrike) { | 
| -        fStrike = fContext->getFontCache()->getStrike(scaler); | 
| -    } | 
| - | 
| -    GrGlyph* glyph = fStrike->getGlyph(packed, scaler); | 
| -    if (NULL == glyph || glyph->fBounds.isEmpty()) { | 
| -        return true; | 
| -    } | 
| - | 
| -    // fallback to color glyph support | 
| -    if (kA8_GrMaskFormat != glyph->fMaskFormat) { | 
| -        return false; | 
| -    } | 
| - | 
| -    SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); | 
| -    SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); | 
| -    SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset); | 
| -    SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset); | 
| - | 
| -    SkScalar scale = fTextRatio; | 
| -    dx *= scale; | 
| -    dy *= scale; | 
| -    width *= scale; | 
| -    height *= scale; | 
| -    sx += dx; | 
| -    sy += dy; | 
| -    SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); | 
| - | 
| -    // check if we clipped out | 
| -    SkRect dstRect; | 
| -    const SkMatrix& ctm = fViewMatrix; | 
| -    (void) ctm.mapRect(&dstRect, glyphRect); | 
| -    if (fClipRect.quickReject(SkScalarTruncToInt(dstRect.left()), | 
| -                              SkScalarTruncToInt(dstRect.top()), | 
| -                              SkScalarTruncToInt(dstRect.right()), | 
| -                              SkScalarTruncToInt(dstRect.bottom()))) { | 
| -        return true; | 
| -    } | 
| - | 
| -    if (NULL == glyph->fPlot) { | 
| -        // needs to be a separate conditional to avoid over-optimization | 
| -        // on Nexus 7 and Nexus 10 | 
| - | 
| -        // If the glyph is too large we fall back to paths | 
| -        if (!uploadGlyph(glyph, scaler)) { | 
| -            if (NULL == glyph->fPath) { | 
| -                SkPath* path = SkNEW(SkPath); | 
| -                if (!scaler->getGlyphPath(glyph->glyphID(), path)) { | 
| -                    // flag the glyph as being dead? | 
| -                    delete path; | 
| -                    return true; | 
| -                } | 
| -                glyph->fPath = path; | 
| -            } | 
| - | 
| -            // flush any accumulated draws before drawing this glyph as a path. | 
| -            this->flush(); | 
| - | 
| -            SkMatrix ctm; | 
| -            ctm.postTranslate(sx - dx, sy - dy); | 
| - | 
| -            SkPath tmpPath(*glyph->fPath); | 
| -            tmpPath.transform(ctm); | 
| - | 
| -            GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); | 
| -            fContext->drawPath(fRenderTarget, fClip, fPaint, fViewMatrix, tmpPath, strokeInfo); | 
| - | 
| -            // remove this glyph from the vertices we need to allocate | 
| -            fTotalVertexCount -= kVerticesPerGlyph; | 
| -            return true; | 
| -        } | 
| -    } | 
| - | 
| -    SkASSERT(glyph->fPlot); | 
| -    GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); | 
| -    glyph->fPlot->setDrawToken(drawToken); | 
| - | 
| -    GrTexture* texture = glyph->fPlot->texture(); | 
| -    SkASSERT(texture); | 
| - | 
| -    if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fTotalVertexCount) { | 
| -        this->flush(); | 
| -        fCurrTexture = texture; | 
| -        fCurrTexture->ref(); | 
| -    } | 
| - | 
| -    bool useColorVerts = !fUseLCDText; | 
| - | 
| -    if (NULL == fVertices) { | 
| -        int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads(); | 
| -        fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices); | 
| -        fVertices = alloc_vertices(fDrawTarget, | 
| -                                   fAllocVertexCount, | 
| -                                   useColorVerts); | 
| -    } | 
| - | 
| -    fVertexBounds.joinNonEmptyArg(glyphRect); | 
| - | 
| -    int u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; | 
| -    int v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; | 
| -    int u1 = u0 + glyph->fBounds.width() - 2*SK_DistanceFieldInset; | 
| -    int v1 = v0 + glyph->fBounds.height() - 2*SK_DistanceFieldInset; | 
| - | 
| -    size_t vertSize = get_vertex_stride(useColorVerts); | 
| -    intptr_t vertex = reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex; | 
| - | 
| -    // V0 | 
| -    SkPoint* position = reinterpret_cast<SkPoint*>(vertex); | 
| -    position->set(glyphRect.fLeft, glyphRect.fTop); | 
| -    if (useColorVerts) { | 
| -        SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); | 
| -        *color = fPaint.getColor(); | 
| -    } | 
| -    SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - | 
| -                                                              sizeof(SkIPoint16)); | 
| -    textureCoords->set(u0, v0); | 
| -    vertex += vertSize; | 
| - | 
| -    // V1 | 
| -    position = reinterpret_cast<SkPoint*>(vertex); | 
| -    position->set(glyphRect.fLeft, glyphRect.fBottom); | 
| -    if (useColorVerts) { | 
| -        SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); | 
| -        *color = fPaint.getColor(); | 
| -    } | 
| -    textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize  - sizeof(SkIPoint16)); | 
| -    textureCoords->set(u0, v1); | 
| -    vertex += vertSize; | 
| - | 
| -    // V2 | 
| -    position = reinterpret_cast<SkPoint*>(vertex); | 
| -    position->set(glyphRect.fRight, glyphRect.fBottom); | 
| -    if (useColorVerts) { | 
| -        SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); | 
| -        *color = fPaint.getColor(); | 
| -    } | 
| -    textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize  - sizeof(SkIPoint16)); | 
| -    textureCoords->set(u1, v1); | 
| -    vertex += vertSize; | 
| - | 
| -    // V3 | 
| -    position = reinterpret_cast<SkPoint*>(vertex); | 
| -    position->set(glyphRect.fRight, glyphRect.fTop); | 
| -    if (useColorVerts) { | 
| -        SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); | 
| -        *color = fPaint.getColor(); | 
| -    } | 
| -    textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize  - sizeof(SkIPoint16)); | 
| -    textureCoords->set(u1, v0); | 
| - | 
| -    fCurrVertex += 4; | 
| - | 
| -    return true; | 
| -} | 
| - | 
| -void GrDistanceFieldTextContext::flush() { | 
| -    if (NULL == fDrawTarget) { | 
| -        return; | 
| -    } | 
| - | 
| -    if (fCurrVertex > 0) { | 
| -        GrPipelineBuilder pipelineBuilder; | 
| -        pipelineBuilder.setFromPaint(fPaint, fRenderTarget, fClip); | 
| - | 
| -        // setup our sampler state for our text texture/atlas | 
| -        SkASSERT(SkIsAlign4(fCurrVertex)); | 
| - | 
| -        // get our current color | 
| -        SkColor filteredColor; | 
| -        SkColorFilter* colorFilter = fSkPaint.getColorFilter(); | 
| -        if (colorFilter) { | 
| -            filteredColor = colorFilter->filterColor(fSkPaint.getColor()); | 
| -        } else { | 
| -            filteredColor = fSkPaint.getColor(); | 
| -        } | 
| -        this->setupCoverageEffect(filteredColor); | 
| - | 
| -        // Set draw state | 
| -        if (fUseLCDText) { | 
| -            // TODO: move supportsRGBCoverage check to setupCoverageEffect and only add LCD | 
| -            // processor if the xp can support it. For now we will simply assume that if | 
| -            // fUseLCDText is true, then we have a known color output. | 
| -            const GrXPFactory* xpFactory = pipelineBuilder.getXPFactory(); | 
| -            if (!xpFactory->supportsRGBCoverage(0, kRGBA_GrColorComponentFlags)) { | 
| -                SkDebugf("LCD Text will not draw correctly.\n"); | 
| -            } | 
| -            SkASSERT(!fCachedGeometryProcessor->hasVertexColor()); | 
| -        } else { | 
| -            // We're using per-vertex color. | 
| -            SkASSERT(fCachedGeometryProcessor->hasVertexColor()); | 
| -        } | 
| -        int nGlyphs = fCurrVertex / kVerticesPerGlyph; | 
| -        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 
| -        fDrawTarget->drawIndexedInstances(&pipelineBuilder, | 
| -                                          fCachedGeometryProcessor.get(), | 
| -                                          kTriangles_GrPrimitiveType, | 
| -                                          nGlyphs, | 
| -                                          kVerticesPerGlyph, | 
| -                                          kIndicesPerGlyph, | 
| -                                          &fVertexBounds); | 
| -        fDrawTarget->resetVertexSource(); | 
| -        fVertices = NULL; | 
| -        fTotalVertexCount -= fCurrVertex; | 
| -        fCurrVertex = 0; | 
| -        SkSafeSetNull(fCurrTexture); | 
| -        fVertexBounds.setLargestInverted(); | 
| -    } | 
| -} | 
| - | 
| -inline void GrDistanceFieldTextContext::finish() { | 
| -    this->flush(); | 
| -    fTotalVertexCount = 0; | 
| - | 
| -    GrTextContext::finish(); | 
| -} | 
| - | 
|  |