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