GrTextContext.cpp revision ac10a2d039c5d52eed66e27cbbc503ab523c1cd5
1ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*
2ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    Copyright 2010 Google Inc.
3ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
4ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    Licensed under the Apache License, Version 2.0 (the "License");
5ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    you may not use this file except in compliance with the License.
6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    You may obtain a copy of the License at
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com         http://www.apache.org/licenses/LICENSE-2.0
9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    Unless required by applicable law or agreed to in writing, software
11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    distributed under the License is distributed on an "AS IS" BASIS,
12ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    See the License for the specific language governing permissions and
14ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    limitations under the License.
15ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
16ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
17ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
18ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrAtlas.h"
19ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrClipIterator.h"
20ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrContext.h"
21ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextContext.h"
22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike.h"
23ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike_impl.h"
24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrFontScaler.h"
25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic const GrVertexLayout VLAYOUT = GrDrawTarget::kTextFormat_VertexLayoutBit;
27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrTextContext::flushGlyphs() {
29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fCurrVertex > 0) {
30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrDrawTarget::AutoStateRestore asr(fDrawTarget);
31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // setup our sampler state for our text texture/atlas
33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode,
35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                               GrSamplerState::kRepeat_WrapMode,
36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                               GrSamplerState::kAlphaMod_SampleMode,
37ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                               !fExtMatrix.isIdentity());
38ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fDrawTarget->setSamplerState(sampler);
39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
40ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(GrIsALIGN4(fCurrVertex));
41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        int nIndices = fCurrVertex + (fCurrVertex >> 1);
42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(fCurrTexture);
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fDrawTarget->setTexture(fCurrTexture);
44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fDrawTarget->setTextureMatrix(GrMatrix::I());
45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fDrawTarget->setIndexSourceToBuffer(fContext->quadIndexBuffer());
46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fDrawTarget->drawIndexed(GrDrawTarget::kTriangles_PrimitiveType,
48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                 0, 0, fCurrVertex, nIndices);
49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fDrawTarget->releaseReservedGeometry();
51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fVertices = NULL;
52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fMaxVertices = 0;
53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCurrVertex = 0;
54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCurrTexture->unref();
55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCurrTexture = NULL;
56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextContext::GrTextContext(GrContext* context, const GrMatrix* extMatrix) {
60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fContext = context;
61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fStrike = NULL;
62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCurrTexture = NULL;
64ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCurrVertex = 0;
65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fClipRect = context->getClip().getBounds();
66ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL != extMatrix) {
68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fExtMatrix = *extMatrix;
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fExtMatrix = GrMatrix::I();
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!fExtMatrix.isIdentity()) {
73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrMatrix inverse;
74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrRect r;
75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        r.set(fClipRect);
76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (fExtMatrix.invert(&inverse)) {
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            inverse.mapRect(&r);
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            r.roundOut(&fClipRect);
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fContext->getViewMatrix(&fOrigViewMatrix);
83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fContext->setViewMatrix(fExtMatrix);
84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fVertices = NULL;
86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fMaxVertices = 0;
87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fDrawTarget = fContext->getTextTarget();
88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextContext::~GrTextContext() {
91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    this->flushGlyphs();
92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fContext->setViewMatrix(fOrigViewMatrix);
93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrTextContext::flush() {
96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    this->flushGlyphs();
97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic inline void setRectFan(GrGpuTextVertex v[4], int l, int t, int r, int b,
100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                              int stride) {
101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    v[0 * stride].setI(l, t);
102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    v[1 * stride].setI(l, b);
103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    v[2 * stride].setI(r, b);
104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    v[3 * stride].setI(r, t);
105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                    GrFixed vx, GrFixed vy,
109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                    GrFontScaler* scaler) {
110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == fStrike) {
111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fStrike = fContext->getFontCache()->getStrike(scaler);
112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == glyph || glyph->fBounds.isEmpty()) {
116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return;
117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
118ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    vx += GrIntToFixed(glyph->fBounds.fLeft);
120ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    vy += GrIntToFixed(glyph->fBounds.fTop);
121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
122ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // keep them as ints until we've done the clip-test
123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrFixed width = glyph->fBounds.width();
124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrFixed height = glyph->fBounds.height();
125ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
126ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // check if we clipped out
127ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (true || NULL == glyph->fAtlas) {
128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        int x = vx >> 16;
129ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        int y = vy >> 16;
130ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (fClipRect.quickReject(x, y, x + width, y + height)) {
131ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com//            Gr_clz(3);    // so we can set a break-point in the debugger
132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            return;
133ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
134ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
135ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == glyph->fAtlas) {
137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (fStrike->getGlyphAtlas(glyph, scaler)) {
138ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            goto HAS_ATLAS;
139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
140ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // try to purge
141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fContext->getFontCache()->purgeExceptFor(fStrike);
142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (fStrike->getGlyphAtlas(glyph, scaler)) {
143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            goto HAS_ATLAS;
144ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
145ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // Draw as a path, so we flush any accumulated glyphs first
147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        this->flushGlyphs();
148ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
149ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (NULL == glyph->fPath) {
150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
151ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            GrPath* path = new GrPath;
152ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
153ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                // flag the glyph as being dead?
154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                delete path;
155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                return;
156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            }
157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            glyph->fPath = path;
158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrPath::Iter iter(*glyph->fPath);
160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        bool useTexture = false;
161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrPoint translate;
162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)),
163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                      GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop)));
164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fContext->drawPath(&iter, GrContext::kWinding_PathFill,
165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                              useTexture, &translate);
166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return;
167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comHAS_ATLAS:
170ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(glyph->fAtlas);
171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // now promote them to fixed
173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    width = GrIntToFixed(width);
174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    height = GrIntToFixed(height);
175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrTexture* texture = glyph->fAtlas->texture();
177ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(texture);
178ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        this->flushGlyphs();
181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCurrTexture = texture;
182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCurrTexture->ref();
183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
184ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == fVertices) {
186ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // If we need to reserve vertices allow the draw target to suggest
187ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // a number of verts to reserve and whether to perform a flush.
188ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fMaxVertices = kMinRequestedVerts;
189ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        bool flush = fDrawTarget->geometryHints(VLAYOUT,
190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                               &fMaxVertices,
191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                               NULL);
192ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (flush) {
193ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            this->flushGlyphs();
194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fContext->flushText();
195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fDrawTarget = fContext->getTextTarget();
196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fMaxVertices = kDefaultRequestedVerts;
197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // ignore return, no point in flushing again.
198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fDrawTarget->geometryHints(VLAYOUT,
199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                       &fMaxVertices,
200ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                       NULL);
201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        if (fMaxVertices < kMinRequestedVerts) {
204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fMaxVertices = kDefaultRequestedVerts;
205ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        } else if (fMaxVertices > (fContext->maxQuadsInIndexBuffer() * 4)) {
206ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // don't exceed the limit of the index buffer
207ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fMaxVertices = (fContext->maxQuadsInIndexBuffer() * 4);
208ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
209ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        bool success = fDrawTarget->reserveAndLockGeometry(VLAYOUT,
210ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                                           fMaxVertices, 0,
211ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                                           (void**)&fVertices,
212ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                                           NULL);
213ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAlwaysAssert(success);
214ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
215ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
216ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrFixed tx = GrIntToFixed(glyph->fAtlasLocation.fX);
217ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrFixed ty = GrIntToFixed(glyph->fAtlasLocation.fY);
218ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
219ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_GL_TEXT_TEXTURE_NORMALIZED
220ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int x = vx >> 16;
221ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int y = vy >> 16;
222ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int w = width >> 16;
223ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int h = height >> 16;
224ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
225ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    setRectFan(&fVertices[2*fCurrVertex], x, y, x + w, y + h, 2);
226ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    setRectFan(&fVertices[2*fCurrVertex+1],
227ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com               texture->normalizeFixedX(tx),
228ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com               texture->normalizeFixedY(ty),
229ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com               texture->normalizeFixedX(tx + width),
230ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com               texture->normalizeFixedY(ty + height),
231ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com               2);
232ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#else
233ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fVertices[2*fCurrVertex].setXRectFan(vx, vy, vx + width, vy + height,
234ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                        2 * sizeof(GrGpuTextVertex));
235ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fVertices[2*fCurrVertex+1].setXRectFan(texture->normalizeFixedX(tx),
236ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          texture->normalizeFixedY(ty),
237ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          texture->normalizeFixedX(tx + width),
238ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          texture->normalizeFixedY(ty + height),
239ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          2 * sizeof(GrGpuTextVertex));
240ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
241ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCurrVertex += 4;
242ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
243ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
244ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
245