105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2010 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */
805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrTextContext.h"
1205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrAtlas.h"
1305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrContext.h"
1405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrTextStrike.h"
1505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrTextStrike_impl.h"
1605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrFontScaler.h"
1705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrIndexBuffer.h"
1805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrGpuVertex.h"
1905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrDrawTarget.h"
2005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerenum {
220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    kGlyphMaskStage = GrPaint::kTotalStages,
230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger};
2405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrTextContext::flushGlyphs() {
2605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (fCurrVertex > 0) {
2705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrDrawTarget::AutoStateRestore asr(fDrawTarget);
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrDrawState* drawState = fDrawTarget->drawState();
2905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // setup our sampler state for our text texture/atlas
3035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        GrSamplerState::Filter filter;
3135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (fExtMatrix.isIdentity()) {
3235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            filter = GrSamplerState::kNearest_Filter;
3335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        } else {
3435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            filter = GrSamplerState::kBilinear_Filter;
3535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        drawState->sampler(kGlyphMaskStage)->reset(
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrSamplerState::kRepeat_WrapMode,filter);
3805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrAssert(GrIsALIGN4(fCurrVertex));
4005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int nIndices = fCurrVertex + (fCurrVertex >> 1);
4105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrAssert(fCurrTexture);
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        drawState->setTexture(kGlyphMaskStage, fCurrTexture);
43137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger
4487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
45137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
46137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger                kISA_BlendCoeff != fPaint.fDstBlendCoeff ||
470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                fPaint.hasTexture()) {
48137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger                GrPrintf("LCD Text will not draw correctly.\n");
49137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            }
50137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // setup blend so that we get mask * paintColor + (1-mask)*dstColor
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            drawState->setBlendConstant(fPaint.fColor);
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            drawState->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff);
53137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // don't modulate by the paint's color in the frag since we're
54137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // already doing it via the blend const.
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            drawState->setColor(0xffffffff);
56137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        } else {
57137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // set back to normal in case we took LCD path previously.
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            drawState->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff);
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            drawState->setColor(fPaint.fColor);
60137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        }
61137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger
6205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
6305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
6405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fDrawTarget->drawIndexed(kTriangles_PrimitiveType,
6505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                 0, 0, fCurrVertex, nIndices);
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fDrawTarget->resetVertexSource();
6705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fVertices = NULL;
6805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fMaxVertices = 0;
6905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrVertex = 0;
7005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture->unref();
7105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture = NULL;
7205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
7305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
7405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
7505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerGrTextContext::GrTextContext(GrContext* context,
7605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                             const GrPaint& paint,
7705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                             const GrMatrix* extMatrix) : fPaint(paint) {
7805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fContext = context;
7905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fStrike = NULL;
8005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
8105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fCurrTexture = NULL;
8205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fCurrVertex = 0;
8305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
8405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL != extMatrix) {
8505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fExtMatrix = *extMatrix;
8605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else {
8705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fExtMatrix = GrMatrix::I();
8805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
8905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (context->getClip().hasConservativeBounds()) {
9005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (!fExtMatrix.isIdentity()) {
9105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            GrMatrix inverse;
9205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            GrRect r = context->getClip().getConservativeBounds();
9305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            if (fExtMatrix.invert(&inverse)) {
9405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                inverse.mapRect(&r);
9505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                r.roundOut(&fClipRect);
9605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            }
9705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        } else {
9805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            context->getClip().getConservativeBounds().roundOut(&fClipRect);
9905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
10005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else {
10105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fClipRect.setLargest();
10205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
10305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
10405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // save the context's original matrix off and restore in destructor
10505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // this must be done before getTextTarget.
10605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fOrigViewMatrix = fContext->getMatrix();
10705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fContext->setMatrix(fExtMatrix);
10805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /*
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     We need to call preConcatMatrix with our viewmatrix's inverse, for each
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     texture and mask in the paint. However, computing the inverse can be
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     expensive, and its possible we may not have any textures or masks, so these
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     two loops are written such that we only compute the inverse (once) if we
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     need it. We do this on our copy of the paint rather than directly on the
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     draw target because we re-provide the paint to the context when we have
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     to flush our glyphs or draw a glyph as a path midstream.
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    */
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool invVMComputed = false;
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrMatrix invVM;
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int t = 0; t < GrPaint::kMaxTextures; ++t) {
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (NULL != fPaint.getTexture(t)) {
1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (invVMComputed || fOrigViewMatrix.invert(&invVM)) {
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                invVMComputed = true;
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                fPaint.textureSampler(t)->preConcatMatrix(invVM);
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int m = 0; m < GrPaint::kMaxMasks; ++m) {
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (NULL != fPaint.getMask(m)) {
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (invVMComputed || fOrigViewMatrix.invert(&invVM)) {
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                invVMComputed = true;
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                fPaint.maskSampler(m)->preConcatMatrix(invVM);
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fDrawTarget = fContext->getTextTarget(fPaint);
1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fVertices = NULL;
1400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fMaxVertices = 0;
1410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fVertexLayout =
1430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        GrDrawTarget::kTextFormat_VertexLayoutBit |
1440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        GrDrawTarget::StageTexCoordVertexLayoutBit(kGlyphMaskStage, 0);
1450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    int stageMask = paint.getActiveStageMask();
1470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (stageMask) {
1480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        for (int i = 0; i < GrPaint::kTotalStages; ++i) {
1490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if ((1 << i) & stageMask) {
1500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                fVertexLayout |=
1510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                    GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
1520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                GrAssert(i != kGlyphMaskStage);
1530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
15405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
15505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
15605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
15705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
15805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerGrTextContext::~GrTextContext() {
15905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    this->flushGlyphs();
16005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fContext->setMatrix(fOrigViewMatrix);
16105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
16205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
16305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrTextContext::flush() {
16405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    this->flushGlyphs();
16505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
16605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
16705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic inline void setRectFan(GrGpuTextVertex v[4], int l, int t, int r, int b,
16805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                              int stride) {
16905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[0 * stride].setI(l, t);
17005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[1 * stride].setI(l, b);
17105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[2 * stride].setI(r, b);
17205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[3 * stride].setI(r, t);
17305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
17405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
17505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
17605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                    GrFixed vx, GrFixed vy,
17705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                    GrFontScaler* scaler) {
17805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == fStrike) {
17905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fStrike = fContext->getFontCache()->getStrike(scaler);
18005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
18105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
18205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
18305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == glyph || glyph->fBounds.isEmpty()) {
18405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return;
18505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
18605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
18705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    vx += GrIntToFixed(glyph->fBounds.fLeft);
18805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    vy += GrIntToFixed(glyph->fBounds.fTop);
18905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
19005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // keep them as ints until we've done the clip-test
19105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed width = glyph->fBounds.width();
19205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed height = glyph->fBounds.height();
19305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
19405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // check if we clipped out
19505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (true || NULL == glyph->fAtlas) {
19605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int x = vx >> 16;
19705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int y = vy >> 16;
19805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fClipRect.quickReject(x, y, x + width, y + height)) {
19905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//            Gr_clz(3);    // so we can set a break-point in the debugger
20005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            return;
20105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
20205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
20305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
20405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == glyph->fAtlas) {
20505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fStrike->getGlyphAtlas(glyph, scaler)) {
20605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            goto HAS_ATLAS;
20705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
20887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
20987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        // before we purge the cache, we must flush any accumulated draws
21087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        this->flushGlyphs();
21105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fContext->flushText();
21205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
21305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // try to purge
21405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fContext->getFontCache()->purgeExceptFor(fStrike);
21505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fStrike->getGlyphAtlas(glyph, scaler)) {
21605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            goto HAS_ATLAS;
21705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
21805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
21905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (NULL == glyph->fPath) {
22005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            GrPath* path = new GrPath;
22105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
22205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                // flag the glyph as being dead?
22305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                delete path;
22405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                return;
22505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            }
22605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            glyph->fPath = path;
22705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
2280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
22905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrPoint translate;
23005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)),
23105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                      GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop)));
2320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        fContext->drawPath(fPaint, *glyph->fPath, kWinding_PathFill,
23305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                           &translate);
23405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return;
23505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
23605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
23705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerHAS_ATLAS:
23805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrAssert(glyph->fAtlas);
23905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
24005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // now promote them to fixed
24105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    width = GrIntToFixed(width);
24205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    height = GrIntToFixed(height);
24305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
24405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrTexture* texture = glyph->fAtlas->texture();
24505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrAssert(texture);
24605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
24705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
24805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        this->flushGlyphs();
24905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture = texture;
25005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture->ref();
25105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
25205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
25305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == fVertices) {
25405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // If we need to reserve vertices allow the draw target to suggest
25505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // a number of verts to reserve and whether to perform a flush.
25605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fMaxVertices = kMinRequestedVerts;
25705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        bool flush = fDrawTarget->geometryHints(fVertexLayout,
25805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                               &fMaxVertices,
25905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                               NULL);
26005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (flush) {
26105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            this->flushGlyphs();
26205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fContext->flushText();
26305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fDrawTarget = fContext->getTextTarget(fPaint);
26405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fMaxVertices = kDefaultRequestedVerts;
26505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            // ignore return, no point in flushing again.
26605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fDrawTarget->geometryHints(fVertexLayout,
26705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                       &fMaxVertices,
26805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                       NULL);
26905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
27005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
27205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fMaxVertices < kMinRequestedVerts) {
27305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fMaxVertices = kDefaultRequestedVerts;
27405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        } else if (fMaxVertices > maxQuadVertices) {
27505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            // don't exceed the limit of the index buffer
27605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fMaxVertices = maxQuadVertices;
27705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bool success = fDrawTarget->reserveVertexSpace(fVertexLayout,
2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                   fMaxVertices,
2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                   GrTCast<void**>(&fVertices));
28105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrAlwaysAssert(success);
28205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
28305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
28405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed tx = GrIntToFixed(glyph->fAtlasLocation.fX);
28505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed ty = GrIntToFixed(glyph->fAtlasLocation.fY);
28605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
28705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#if GR_GL_TEXT_TEXTURE_NORMALIZED
28805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int x = vx >> 16;
28905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int y = vy >> 16;
29005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int w = width >> 16;
29105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int h = height >> 16;
29205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
29305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    setRectFan(&fVertices[2*fCurrVertex], x, y, x + w, y + h, 2);
29405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    setRectFan(&fVertices[2*fCurrVertex+1],
29505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedX(tx),
29605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedY(ty),
29705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedX(tx + width),
29805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedY(ty + height),
29905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               2);
30005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#else
30105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fVertices[2*fCurrVertex].setXRectFan(vx, vy, vx + width, vy + height,
30205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                        2 * sizeof(GrGpuTextVertex));
30305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fVertices[2*fCurrVertex+1].setXRectFan(texture->normalizeFixedX(tx),
30405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          texture->normalizeFixedY(ty),
30505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          texture->normalizeFixedX(tx + width),
30605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          texture->normalizeFixedY(ty + height),
30705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          2 * sizeof(GrGpuTextVertex));
30805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif
30905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fCurrVertex += 4;
31005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
31105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
31205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
313