105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger/*
205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    Copyright 2010 Google Inc.
305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    Licensed under the Apache License, Version 2.0 (the "License");
505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    you may not use this file except in compliance with the License.
605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    You may obtain a copy of the License at
705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger         http://www.apache.org/licenses/LICENSE-2.0
905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    Unless required by applicable law or agreed to in writing, software
1105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    distributed under the License is distributed on an "AS IS" BASIS,
1205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    See the License for the specific language governing permissions and
1405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    limitations under the License.
1505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */
1605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrTextContext.h"
1905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrAtlas.h"
2005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrContext.h"
2105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrTextStrike.h"
2205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrTextStrike_impl.h"
2305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrFontScaler.h"
2405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrIndexBuffer.h"
2505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrGpuVertex.h"
2605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "GrDrawTarget.h"
2705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerenum {
290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    kGlyphMaskStage = GrPaint::kTotalStages,
300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger};
3105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrTextContext::flushGlyphs() {
3305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (fCurrVertex > 0) {
3405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrDrawTarget::AutoStateRestore asr(fDrawTarget);
3505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // setup our sampler state for our text texture/atlas
3735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        GrSamplerState::Filter filter;
3835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (fExtMatrix.isIdentity()) {
3935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            filter = GrSamplerState::kNearest_Filter;
4035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        } else {
4135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            filter = GrSamplerState::kBilinear_Filter;
4235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
4305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode,
4405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                               GrSamplerState::kRepeat_WrapMode,
4535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                               filter);
460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        fDrawTarget->setSamplerState(kGlyphMaskStage, sampler);
4705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
4805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrAssert(GrIsALIGN4(fCurrVertex));
4905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int nIndices = fCurrVertex + (fCurrVertex >> 1);
5005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrAssert(fCurrTexture);
510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        fDrawTarget->setTexture(kGlyphMaskStage, fCurrTexture);
52137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger
5387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
54137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
55137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger                kISA_BlendCoeff != fPaint.fDstBlendCoeff ||
560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                fPaint.hasTexture()) {
57137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger                GrPrintf("LCD Text will not draw correctly.\n");
58137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            }
59137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // setup blend so that we get mask * paintColor + (1-mask)*dstColor
60137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            fDrawTarget->setBlendConstant(fPaint.fColor);
61137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            fDrawTarget->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff);
62137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // don't modulate by the paint's color in the frag since we're
63137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // already doing it via the blend const.
64137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            fDrawTarget->setColor(0xffffffff);
65137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        } else {
66137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            // set back to normal in case we took LCD path previously.
67137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            fDrawTarget->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff);
68137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger            fDrawTarget->setColor(fPaint.fColor);
69137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        }
70137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger
7105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
7205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
7305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fDrawTarget->drawIndexed(kTriangles_PrimitiveType,
7405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                 0, 0, fCurrVertex, nIndices);
7505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fDrawTarget->releaseReservedGeometry();
7605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fVertices = NULL;
7705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fMaxVertices = 0;
7805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrVertex = 0;
7905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture->unref();
8005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture = NULL;
8105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
8205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
8305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
8405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerGrTextContext::GrTextContext(GrContext* context,
8505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                             const GrPaint& paint,
8605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                             const GrMatrix* extMatrix) : fPaint(paint) {
8705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fContext = context;
8805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fStrike = NULL;
8905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fCurrTexture = NULL;
9105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fCurrVertex = 0;
9205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL != extMatrix) {
9405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fExtMatrix = *extMatrix;
9505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else {
9605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fExtMatrix = GrMatrix::I();
9705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
9805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (context->getClip().hasConservativeBounds()) {
9905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (!fExtMatrix.isIdentity()) {
10005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            GrMatrix inverse;
10105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            GrRect r = context->getClip().getConservativeBounds();
10205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            if (fExtMatrix.invert(&inverse)) {
10305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                inverse.mapRect(&r);
10405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                r.roundOut(&fClipRect);
10505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            }
10605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        } else {
10705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            context->getClip().getConservativeBounds().roundOut(&fClipRect);
10805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
10905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else {
11005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fClipRect.setLargest();
11105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
11205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
11305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // save the context's original matrix off and restore in destructor
11405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // this must be done before getTextTarget.
11505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fOrigViewMatrix = fContext->getMatrix();
11605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fContext->setMatrix(fExtMatrix);
11705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fDrawTarget = fContext->getTextTarget(fPaint);
1190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fVertices = NULL;
1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fMaxVertices = 0;
1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    fVertexLayout =
1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        GrDrawTarget::kTextFormat_VertexLayoutBit |
1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        GrDrawTarget::StageTexCoordVertexLayoutBit(kGlyphMaskStage, 0);
1260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    int stageMask = paint.getActiveStageMask();
1280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (stageMask) {
12905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrMatrix inverseViewMatrix;
13005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fOrigViewMatrix.invert(&inverseViewMatrix)) {
1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            fDrawTarget->preConcatSamplerMatrices(stageMask,
1320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                                                  inverseViewMatrix);
1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        }
1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        for (int i = 0; i < GrPaint::kTotalStages; ++i) {
1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if ((1 << i) & stageMask) {
1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                fVertexLayout |=
1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                    GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                GrAssert(i != kGlyphMaskStage);
1390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
14005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
14105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
14205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
14305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
14405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
14505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerGrTextContext::~GrTextContext() {
14605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    this->flushGlyphs();
14705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fContext->setMatrix(fOrigViewMatrix);
14805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
14905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
15005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrTextContext::flush() {
15105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    this->flushGlyphs();
15205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
15305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
15405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic inline void setRectFan(GrGpuTextVertex v[4], int l, int t, int r, int b,
15505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                              int stride) {
15605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[0 * stride].setI(l, t);
15705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[1 * stride].setI(l, b);
15805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[2 * stride].setI(r, b);
15905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    v[3 * stride].setI(r, t);
16005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
16105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
16205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
16305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                    GrFixed vx, GrFixed vy,
16405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                    GrFontScaler* scaler) {
16505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == fStrike) {
16605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fStrike = fContext->getFontCache()->getStrike(scaler);
16705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
16805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
16905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
17005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == glyph || glyph->fBounds.isEmpty()) {
17105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return;
17205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
17305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
17405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    vx += GrIntToFixed(glyph->fBounds.fLeft);
17505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    vy += GrIntToFixed(glyph->fBounds.fTop);
17605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
17705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // keep them as ints until we've done the clip-test
17805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed width = glyph->fBounds.width();
17905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed height = glyph->fBounds.height();
18005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
18105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // check if we clipped out
18205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (true || NULL == glyph->fAtlas) {
18305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int x = vx >> 16;
18405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int y = vy >> 16;
18505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fClipRect.quickReject(x, y, x + width, y + height)) {
18605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//            Gr_clz(3);    // so we can set a break-point in the debugger
18705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            return;
18805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
18905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
19005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
19105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == glyph->fAtlas) {
19205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fStrike->getGlyphAtlas(glyph, scaler)) {
19305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            goto HAS_ATLAS;
19405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
19587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
19687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        // before we purge the cache, we must flush any accumulated draws
19787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        this->flushGlyphs();
19805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fContext->flushText();
19905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
20005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // try to purge
20105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fContext->getFontCache()->purgeExceptFor(fStrike);
20205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fStrike->getGlyphAtlas(glyph, scaler)) {
20305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            goto HAS_ATLAS;
20405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
20505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
20605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (NULL == glyph->fPath) {
20705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            GrPath* path = new GrPath;
20805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
20905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                // flag the glyph as being dead?
21005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                delete path;
21105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                return;
21205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            }
21305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            glyph->fPath = path;
21405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
2150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
21605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrPoint translate;
21705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)),
21805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                      GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop)));
2190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        fContext->drawPath(fPaint, *glyph->fPath, kWinding_PathFill,
22005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                           &translate);
22105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return;
22205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
22305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
22405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerHAS_ATLAS:
22505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrAssert(glyph->fAtlas);
22605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
22705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // now promote them to fixed
22805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    width = GrIntToFixed(width);
22905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    height = GrIntToFixed(height);
23005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
23105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrTexture* texture = glyph->fAtlas->texture();
23205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrAssert(texture);
23305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
23405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
23505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        this->flushGlyphs();
23605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture = texture;
23705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fCurrTexture->ref();
23805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
23905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
24005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (NULL == fVertices) {
24105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // If we need to reserve vertices allow the draw target to suggest
24205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        // a number of verts to reserve and whether to perform a flush.
24305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fMaxVertices = kMinRequestedVerts;
24405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        bool flush = fDrawTarget->geometryHints(fVertexLayout,
24505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                               &fMaxVertices,
24605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                               NULL);
24705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (flush) {
24805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            this->flushGlyphs();
24905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fContext->flushText();
25005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fDrawTarget = fContext->getTextTarget(fPaint);
25105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fMaxVertices = kDefaultRequestedVerts;
25205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            // ignore return, no point in flushing again.
25305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fDrawTarget->geometryHints(fVertexLayout,
25405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                       &fMaxVertices,
25505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                       NULL);
25605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
25705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
25805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->size() / (6 * sizeof(uint16_t));
25905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (fMaxVertices < kMinRequestedVerts) {
26005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fMaxVertices = kDefaultRequestedVerts;
26105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        } else if (fMaxVertices > maxQuadVertices) {
26205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            // don't exceed the limit of the index buffer
26305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fMaxVertices = maxQuadVertices;
26405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
26505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        bool success = fDrawTarget->reserveAndLockGeometry(fVertexLayout,
26605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                                           fMaxVertices, 0,
26705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                                   GrTCast<void**>(&fVertices),
26805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                                           NULL);
26905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        GrAlwaysAssert(success);
27005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
27105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
27205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed tx = GrIntToFixed(glyph->fAtlasLocation.fX);
27305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    GrFixed ty = GrIntToFixed(glyph->fAtlasLocation.fY);
27405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
27505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#if GR_GL_TEXT_TEXTURE_NORMALIZED
27605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int x = vx >> 16;
27705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int y = vy >> 16;
27805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int w = width >> 16;
27905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int h = height >> 16;
28005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
28105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    setRectFan(&fVertices[2*fCurrVertex], x, y, x + w, y + h, 2);
28205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    setRectFan(&fVertices[2*fCurrVertex+1],
28305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedX(tx),
28405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedY(ty),
28505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedX(tx + width),
28605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               texture->normalizeFixedY(ty + height),
28705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger               2);
28805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#else
28905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fVertices[2*fCurrVertex].setXRectFan(vx, vy, vx + width, vy + height,
29005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                        2 * sizeof(GrGpuTextVertex));
29105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fVertices[2*fCurrVertex+1].setXRectFan(texture->normalizeFixedX(tx),
29205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          texture->normalizeFixedY(ty),
29305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          texture->normalizeFixedX(tx + width),
29405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          texture->normalizeFixedY(ty + height),
29505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger                                          2 * sizeof(GrGpuTextVertex));
29605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif
29705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fCurrVertex += 4;
29805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
29905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
30005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
301