+
+static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
+ unsigned r = SkColorGetR(c);
+ unsigned g = SkColorGetG(c);
+ unsigned b = SkColorGetB(c);
+ return GrColorPackRGBA(r, g, b, 0xff);
+}
+
+void GrBitmapTextContext::flush() {
+ if (NULL == fDrawTarget) {
+ return;
+ }
+
+ GrDrawState* drawState = fDrawTarget->drawState();
+ GrDrawState::AutoRestoreEffects are(drawState);
+ drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
+
+ if (fCurrVertex > 0) {
+ // setup our sampler state for our text texture/atlas
+ SkASSERT(SkIsAlign4(fCurrVertex));
+ SkASSERT(fCurrTexture);
+ GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
+
+ // This effect could be stored with one of the cache objects (atlas?)
+ if (kARGB_GrMaskFormat == fCurrMaskFormat) {
+ GrFragmentProcessor* fragProcessor = GrSimpleTextureEffect::Create(fCurrTexture,
+ SkMatrix::I(),
+ params);
+ drawState->addColorProcessor(fragProcessor)->unref();
+ } else {
+ uint32_t textureUniqueID = fCurrTexture->getUniqueID();
+ if (textureUniqueID != fEffectTextureUniqueID) {
+ fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
+ params));
+ fEffectTextureUniqueID = textureUniqueID;
+ }
+
+ drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+ }
+
+ SkASSERT(fStrike);
+ switch (fCurrMaskFormat) {
+ // Color bitmap text
+ case kARGB_GrMaskFormat:
+ SkASSERT(!drawState->hasColorVertexAttribute());
+ drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+ drawState->setAlpha(fSkPaint.getAlpha());
+ break;
+ // LCD text
+ case kA888_GrMaskFormat:
+ case kA565_GrMaskFormat: {
+ if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
+ kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
+ fPaint.numColorStages()) {
+ SkDebugf("LCD Text will not draw correctly.\n");
+ }
+ SkASSERT(!drawState->hasColorVertexAttribute());
+ // We don't use the GrPaint's color in this case because it's been premultiplied by
+ // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
+ // the mask texture color. The end result is that we get
+ // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
+ int a = SkColorGetA(fSkPaint.getColor());
+ // paintAlpha
+ drawState->setColor(SkColorSetARGB(a, a, a, a));
+ // paintColor
+ drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
+ drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+ break;
+ }
+ // Grayscale/BW text
+ case kA8_GrMaskFormat:
+ // set back to normal in case we took LCD path previously.
+ drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+ // We're using per-vertex color.
+ SkASSERT(drawState->hasColorVertexAttribute());
+ break;
+ default:
+ SkFAIL("Unexpected mask format.");
+ }
+ int nGlyphs = fCurrVertex / kVerticesPerGlyph;
+ fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
+ fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
+ nGlyphs,
+ kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds);
+
+ fDrawTarget->resetVertexSource();
+ fVertices = NULL;
+ fAllocVertexCount = 0;
+ // reset to be those that are left
+ fTotalVertexCount -= fCurrVertex;
+ fCurrVertex = 0;
+ fVertexBounds.setLargestInverted();
+ SkSafeSetNull(fCurrTexture);
+ }
+}
+
+inline void GrBitmapTextContext::finish() {
+ this->flush();
+ fTotalVertexCount = 0;
+
+ GrTextContext::finish();
+}
+