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