| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrBitmapTextContext.h" | 8 #include "GrBitmapTextContext.h" |
| 9 #include "GrAtlas.h" | 9 #include "GrAtlas.h" |
| 10 #include "GrDrawTarget.h" | 10 #include "GrDrawTarget.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 fCurrVertex = 0; | 60 fCurrVertex = 0; |
| 61 fEffectTextureUniqueID = SK_InvalidUniqueID; | 61 fEffectTextureUniqueID = SK_InvalidUniqueID; |
| 62 | 62 |
| 63 fVertices = NULL; | 63 fVertices = NULL; |
| 64 fMaxVertices = 0; | 64 fMaxVertices = 0; |
| 65 | 65 |
| 66 fVertexBounds.setLargestInverted(); | 66 fVertexBounds.setLargestInverted(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 GrBitmapTextContext::~GrBitmapTextContext() { | 69 GrBitmapTextContext::~GrBitmapTextContext() { |
| 70 this->flushGlyphs(); | 70 this->flush(); |
| 71 } | 71 } |
| 72 | 72 |
| 73 bool GrBitmapTextContext::canDraw(const SkPaint& paint) { | 73 bool GrBitmapTextContext::canDraw(const SkPaint& paint) { |
| 74 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix()); | 74 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix()); |
| 75 } | 75 } |
| 76 | 76 |
| 77 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { | |
| 78 unsigned r = SkColorGetR(c); | |
| 79 unsigned g = SkColorGetG(c); | |
| 80 unsigned b = SkColorGetB(c); | |
| 81 return GrColorPackRGBA(r, g, b, 0xff); | |
| 82 } | |
| 83 | |
| 84 void GrBitmapTextContext::flushGlyphs() { | |
| 85 if (NULL == fDrawTarget) { | |
| 86 return; | |
| 87 } | |
| 88 | |
| 89 GrDrawState* drawState = fDrawTarget->drawState(); | |
| 90 GrDrawState::AutoRestoreEffects are(drawState); | |
| 91 drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); | |
| 92 | |
| 93 if (fCurrVertex > 0) { | |
| 94 // setup our sampler state for our text texture/atlas | |
| 95 SkASSERT(SkIsAlign4(fCurrVertex)); | |
| 96 SkASSERT(fCurrTexture); | |
| 97 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon
e_FilterMode); | |
| 98 | |
| 99 uint32_t textureUniqueID = fCurrTexture->getUniqueID(); | |
| 100 | |
| 101 if (textureUniqueID != fEffectTextureUniqueID) { | |
| 102 fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(f
CurrTexture, | |
| 103 p
arams)); | |
| 104 fEffectTextureUniqueID = textureUniqueID; | |
| 105 } | |
| 106 | |
| 107 // This effect could be stored with one of the cache objects (atlas?) | |
| 108 drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); | |
| 109 SkASSERT(fStrike); | |
| 110 switch (fStrike->getMaskFormat()) { | |
| 111 // Color bitmap text | |
| 112 case kARGB_GrMaskFormat: | |
| 113 SkASSERT(!drawState->hasColorVertexAttribute()); | |
| 114 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); | |
| 115 drawState->setColor(0xffffffff); | |
| 116 break; | |
| 117 // LCD text | |
| 118 case kA888_GrMaskFormat: | |
| 119 case kA565_GrMaskFormat: { | |
| 120 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || | |
| 121 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || | |
| 122 fPaint.numColorStages()) { | |
| 123 GrPrintf("LCD Text will not draw correctly.\n"); | |
| 124 } | |
| 125 SkASSERT(!drawState->hasColorVertexAttribute()); | |
| 126 // We don't use the GrPaint's color in this case because it's be
en premultiplied by | |
| 127 // alpha. Instead we feed in a non-premultiplied color, and mult
iply its alpha by | |
| 128 // the mask texture color. The end result is that we get | |
| 129 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*d
stColor | |
| 130 int a = SkColorGetA(fSkPaint.getColor()); | |
| 131 // paintAlpha | |
| 132 drawState->setColor(SkColorSetARGB(a, a, a, a)); | |
| 133 // paintColor | |
| 134 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSk
Paint.getColor())); | |
| 135 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff)
; | |
| 136 break; | |
| 137 } | |
| 138 // Grayscale/BW text | |
| 139 case kA8_GrMaskFormat: | |
| 140 // set back to normal in case we took LCD path previously. | |
| 141 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); | |
| 142 // We're using per-vertex color. | |
| 143 SkASSERT(drawState->hasColorVertexAttribute()); | |
| 144 break; | |
| 145 default: | |
| 146 SkFAIL("Unexepected mask format."); | |
| 147 } | |
| 148 int nGlyphs = fCurrVertex / 4; | |
| 149 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | |
| 150 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, | |
| 151 nGlyphs, | |
| 152 4, 6, &fVertexBounds); | |
| 153 | |
| 154 fDrawTarget->resetVertexSource(); | |
| 155 fVertices = NULL; | |
| 156 fMaxVertices = 0; | |
| 157 fCurrVertex = 0; | |
| 158 fVertexBounds.setLargestInverted(); | |
| 159 SkSafeSetNull(fCurrTexture); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
nt) { | 77 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
nt) { |
| 164 GrTextContext::init(paint, skPaint); | 78 GrTextContext::init(paint, skPaint); |
| 165 | 79 |
| 166 fStrike = NULL; | 80 fStrike = NULL; |
| 167 | 81 |
| 168 fCurrTexture = NULL; | 82 fCurrTexture = NULL; |
| 169 fCurrVertex = 0; | 83 fCurrVertex = 0; |
| 170 | 84 |
| 171 fVertices = NULL; | 85 fVertices = NULL; |
| 172 fMaxVertices = 0; | 86 fMaxVertices = 0; |
| 173 } | 87 } |
| 174 | 88 |
| 175 inline void GrBitmapTextContext::finish() { | |
| 176 this->flushGlyphs(); | |
| 177 | |
| 178 GrTextContext::finish(); | |
| 179 } | |
| 180 | |
| 181 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, | 89 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, |
| 182 const char text[], size_t byteLength, | 90 const char text[], size_t byteLength, |
| 183 SkScalar x, SkScalar y) { | 91 SkScalar x, SkScalar y) { |
| 184 SkASSERT(byteLength == 0 || text != NULL); | 92 SkASSERT(byteLength == 0 || text != NULL); |
| 185 | 93 |
| 186 // nothing to draw | 94 // nothing to draw |
| 187 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { | 95 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { |
| 188 return; | 96 return; |
| 189 } | 97 } |
| 190 | 98 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 | 155 |
| 248 GrContext::AutoMatrix autoMatrix; | 156 GrContext::AutoMatrix autoMatrix; |
| 249 autoMatrix.setIdentity(fContext, &fPaint); | 157 autoMatrix.setIdentity(fContext, &fPaint); |
| 250 | 158 |
| 251 while (text < stop) { | 159 while (text < stop) { |
| 252 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy
Mask); | 160 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy
Mask); |
| 253 | 161 |
| 254 fx += autokern.adjust(glyph); | 162 fx += autokern.adjust(glyph); |
| 255 | 163 |
| 256 if (glyph.fWidth) { | 164 if (glyph.fWidth) { |
| 257 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 165 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 258 glyph.getSubXFixed(), | 166 glyph.getSubXFixed(), |
| 259 glyph.getSubYFixed()), | 167 glyph.getSubYFixed()), |
| 260 SkFixedFloorToFixed(fx), | 168 SkFixedFloorToFixed(fx), |
| 261 SkFixedFloorToFixed(fy), | 169 SkFixedFloorToFixed(fy), |
| 262 fontScaler); | 170 fontScaler); |
| 263 } | 171 } |
| 264 | 172 |
| 265 fx += glyph.fAdvanceX; | 173 fx += glyph.fAdvanceX; |
| 266 fy += glyph.fAdvanceY; | 174 fy += glyph.fAdvanceY; |
| 267 } | 175 } |
| 268 | 176 |
| 269 this->finish(); | 177 this->finish(); |
| 270 } | 178 } |
| 271 | 179 |
| 272 void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
nt, | 180 void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
nt, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 while (text < stop) { | 229 while (text < stop) { |
| 322 SkPoint tmsLoc; | 230 SkPoint tmsLoc; |
| 323 tmsProc(pos, &tmsLoc); | 231 tmsProc(pos, &tmsLoc); |
| 324 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX; | 232 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX; |
| 325 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY; | 233 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY; |
| 326 | 234 |
| 327 const SkGlyph& glyph = glyphCacheProc(cache, &text, | 235 const SkGlyph& glyph = glyphCacheProc(cache, &text, |
| 328 fx & fxMask, fy & fyMask); | 236 fx & fxMask, fy & fyMask); |
| 329 | 237 |
| 330 if (glyph.fWidth) { | 238 if (glyph.fWidth) { |
| 331 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 239 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 332 glyph.getSubXFixed(), | 240 glyph.getSubXFixed(), |
| 333 glyph.getSubYFixed()), | 241 glyph.getSubYFixed()), |
| 334 SkFixedFloorToFixed(fx), | 242 SkFixedFloorToFixed(fx), |
| 335 SkFixedFloorToFixed(fy), | 243 SkFixedFloorToFixed(fy), |
| 336 fontScaler); | 244 fontScaler); |
| 337 } | 245 } |
| 338 pos += scalarsPerPosition; | 246 pos += scalarsPerPosition; |
| 339 } | 247 } |
| 340 } else { | 248 } else { |
| 341 while (text < stop) { | 249 while (text < stop) { |
| 342 const char* currentText = text; | 250 const char* currentText = text; |
| 343 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); | 251 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); |
| 344 | 252 |
| 345 if (metricGlyph.fWidth) { | 253 if (metricGlyph.fWidth) { |
| 346 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) | 254 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) |
| 347 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) | 255 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) |
| 348 SkPoint tmsLoc; | 256 SkPoint tmsLoc; |
| 349 tmsProc(pos, &tmsLoc); | 257 tmsProc(pos, &tmsLoc); |
| 350 SkIPoint fixedLoc; | 258 SkIPoint fixedLoc; |
| 351 alignProc(tmsLoc, metricGlyph, &fixedLoc); | 259 alignProc(tmsLoc, metricGlyph, &fixedLoc); |
| 352 | 260 |
| 353 SkFixed fx = fixedLoc.fX + halfSampleX; | 261 SkFixed fx = fixedLoc.fX + halfSampleX; |
| 354 SkFixed fy = fixedLoc.fY + halfSampleY; | 262 SkFixed fy = fixedLoc.fY + halfSampleY; |
| 355 | 263 |
| 356 // have to call again, now that we've been "aligned" | 264 // have to call again, now that we've been "aligned" |
| 357 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, | 265 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, |
| 358 fx & fxMask, fy & fyMa
sk); | 266 fx & fxMask, fy & fyMa
sk); |
| 359 // the assumption is that the metrics haven't changed | 267 // the assumption is that the metrics haven't changed |
| 360 SkASSERT(prevAdvX == glyph.fAdvanceX); | 268 SkASSERT(prevAdvX == glyph.fAdvanceX); |
| 361 SkASSERT(prevAdvY == glyph.fAdvanceY); | 269 SkASSERT(prevAdvY == glyph.fAdvanceY); |
| 362 SkASSERT(glyph.fWidth); | 270 SkASSERT(glyph.fWidth); |
| 363 | 271 |
| 364 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 272 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 365 glyph.getSubXFixed(), | 273 glyph.getSubXFixed(), |
| 366 glyph.getSubYFixed()), | 274 glyph.getSubYFixed()), |
| 367 SkFixedFloorToFixed(fx), | 275 SkFixedFloorToFixed(fx), |
| 368 SkFixedFloorToFixed(fy), | 276 SkFixedFloorToFixed(fy), |
| 369 fontScaler); | 277 fontScaler); |
| 370 } | 278 } |
| 371 pos += scalarsPerPosition; | 279 pos += scalarsPerPosition; |
| 372 } | 280 } |
| 373 } | 281 } |
| 374 } else { // not subpixel | 282 } else { // not subpixel |
| 375 | 283 |
| 376 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 284 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| 377 while (text < stop) { | 285 while (text < stop) { |
| 378 // the last 2 parameters are ignored | 286 // the last 2 parameters are ignored |
| 379 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 287 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| 380 | 288 |
| 381 if (glyph.fWidth) { | 289 if (glyph.fWidth) { |
| 382 SkPoint tmsLoc; | 290 SkPoint tmsLoc; |
| 383 tmsProc(pos, &tmsLoc); | 291 tmsProc(pos, &tmsLoc); |
| 384 | 292 |
| 385 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //ha
lfSampleX; | 293 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //ha
lfSampleX; |
| 386 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //ha
lfSampleY; | 294 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //ha
lfSampleY; |
| 387 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 295 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 388 glyph.getSubXFixed(), | 296 glyph.getSubXFixed(), |
| 389 glyph.getSubYFixed()), | 297 glyph.getSubYFixed()), |
| 390 SkFixedFloorToFixed(fx), | 298 SkFixedFloorToFixed(fx), |
| 391 SkFixedFloorToFixed(fy), | 299 SkFixedFloorToFixed(fy), |
| 392 fontScaler); | 300 fontScaler); |
| 393 } | 301 } |
| 394 pos += scalarsPerPosition; | 302 pos += scalarsPerPosition; |
| 395 } | 303 } |
| 396 } else { | 304 } else { |
| 397 while (text < stop) { | 305 while (text < stop) { |
| 398 // the last 2 parameters are ignored | 306 // the last 2 parameters are ignored |
| 399 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 307 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| 400 | 308 |
| 401 if (glyph.fWidth) { | 309 if (glyph.fWidth) { |
| 402 SkPoint tmsLoc; | 310 SkPoint tmsLoc; |
| 403 tmsProc(pos, &tmsLoc); | 311 tmsProc(pos, &tmsLoc); |
| 404 | 312 |
| 405 SkIPoint fixedLoc; | 313 SkIPoint fixedLoc; |
| 406 alignProc(tmsLoc, glyph, &fixedLoc); | 314 alignProc(tmsLoc, glyph, &fixedLoc); |
| 407 | 315 |
| 408 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX; | 316 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX; |
| 409 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY; | 317 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY; |
| 410 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 318 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 411 glyph.getSubXFixed(), | 319 glyph.getSubXFixed(), |
| 412 glyph.getSubYFixed()), | 320 glyph.getSubYFixed()), |
| 413 SkFixedFloorToFixed(fx), | 321 SkFixedFloorToFixed(fx), |
| 414 SkFixedFloorToFixed(fy), | 322 SkFixedFloorToFixed(fy), |
| 415 fontScaler); | 323 fontScaler); |
| 416 } | 324 } |
| 417 pos += scalarsPerPosition; | 325 pos += scalarsPerPosition; |
| 418 } | 326 } |
| 419 } | 327 } |
| 420 } | 328 } |
| 421 | 329 |
| 422 this->finish(); | 330 this->finish(); |
| 423 } | 331 } |
| 424 | 332 |
| 425 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, | 333 void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed, |
| 426 SkFixed vx, SkFixed vy, | 334 SkFixed vx, SkFixed vy, |
| 427 GrFontScaler* scaler) { | 335 GrFontScaler* scaler) { |
| 428 if (NULL == fDrawTarget) { | 336 if (NULL == fDrawTarget) { |
| 429 return; | 337 return; |
| 430 } | 338 } |
| 431 | 339 |
| 432 if (NULL == fStrike) { | 340 if (NULL == fStrike) { |
| 433 fStrike = fContext->getFontCache()->getStrike(scaler, false); | 341 fStrike = fContext->getFontCache()->getStrike(scaler, false); |
| 434 } | 342 } |
| 435 | 343 |
| 436 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); | 344 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); |
| 437 if (NULL == glyph || glyph->fBounds.isEmpty()) { | 345 if (NULL == glyph || glyph->fBounds.isEmpty()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 467 goto HAS_ATLAS; | 375 goto HAS_ATLAS; |
| 468 } | 376 } |
| 469 | 377 |
| 470 if (c_DumpFontCache) { | 378 if (c_DumpFontCache) { |
| 471 #ifdef SK_DEVELOPER | 379 #ifdef SK_DEVELOPER |
| 472 fContext->getFontCache()->dump(); | 380 fContext->getFontCache()->dump(); |
| 473 #endif | 381 #endif |
| 474 } | 382 } |
| 475 | 383 |
| 476 // flush any accumulated draws to allow us to free up a plot | 384 // flush any accumulated draws to allow us to free up a plot |
| 477 this->flushGlyphs(); | 385 this->flush(); |
| 478 fContext->flush(); | 386 fContext->flush(); |
| 479 | 387 |
| 480 // we should have an unused plot now | 388 // we should have an unused plot now |
| 481 if (fContext->getFontCache()->freeUnusedPlot(fStrike) && | 389 if (fContext->getFontCache()->freeUnusedPlot(fStrike) && |
| 482 fStrike->addGlyphToAtlas(glyph, scaler)) { | 390 fStrike->addGlyphToAtlas(glyph, scaler)) { |
| 483 goto HAS_ATLAS; | 391 goto HAS_ATLAS; |
| 484 } | 392 } |
| 485 } | 393 } |
| 486 | 394 |
| 487 if (NULL == glyph->fPath) { | 395 if (NULL == glyph->fPath) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 511 glyph->fPlot->setDrawToken(drawToken); | 419 glyph->fPlot->setDrawToken(drawToken); |
| 512 | 420 |
| 513 // now promote them to fixed (TODO: Rethink using fixed pt). | 421 // now promote them to fixed (TODO: Rethink using fixed pt). |
| 514 width = SkIntToFixed(width); | 422 width = SkIntToFixed(width); |
| 515 height = SkIntToFixed(height); | 423 height = SkIntToFixed(height); |
| 516 | 424 |
| 517 GrTexture* texture = glyph->fPlot->texture(); | 425 GrTexture* texture = glyph->fPlot->texture(); |
| 518 SkASSERT(texture); | 426 SkASSERT(texture); |
| 519 | 427 |
| 520 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { | 428 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { |
| 521 this->flushGlyphs(); | 429 this->flush(); |
| 522 fCurrTexture = texture; | 430 fCurrTexture = texture; |
| 523 fCurrTexture->ref(); | 431 fCurrTexture->ref(); |
| 524 } | 432 } |
| 525 | 433 |
| 526 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat(); | 434 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat(); |
| 527 | 435 |
| 528 if (NULL == fVertices) { | 436 if (NULL == fVertices) { |
| 529 // If we need to reserve vertices allow the draw target to suggest | 437 // If we need to reserve vertices allow the draw target to suggest |
| 530 // a number of verts to reserve and whether to perform a flush. | 438 // a number of verts to reserve and whether to perform a flush. |
| 531 fMaxVertices = kMinRequestedVerts; | 439 fMaxVertices = kMinRequestedVerts; |
| 532 if (useColorVerts) { | 440 if (useColorVerts) { |
| 533 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri
bs>( | 441 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri
bs>( |
| 534 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize); | 442 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize); |
| 535 } else { | 443 } else { |
| 536 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | 444 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 537 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); | 445 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); |
| 538 } | 446 } |
| 539 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); | 447 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); |
| 540 if (flush) { | 448 if (flush) { |
| 541 this->flushGlyphs(); | 449 this->flush(); |
| 542 fContext->flush(); | 450 fContext->flush(); |
| 543 if (useColorVerts) { | 451 if (useColorVerts) { |
| 544 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA
ttribs>( | 452 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA
ttribs>( |
| 545 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSiz
e); | 453 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSiz
e); |
| 546 } else { | 454 } else { |
| 547 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | 455 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 548 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); | 456 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); |
| 549 } | 457 } |
| 550 } | 458 } |
| 551 fMaxVertices = kDefaultRequestedVerts; | 459 fMaxVertices = kDefaultRequestedVerts; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 } | 508 } |
| 601 // color comes after position. | 509 // color comes after position. |
| 602 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); | 510 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); |
| 603 for (int i = 0; i < 4; ++i) { | 511 for (int i = 0; i < 4; ++i) { |
| 604 *colors = fPaint.getColor(); | 512 *colors = fPaint.getColor(); |
| 605 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors
) + vertSize); | 513 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors
) + vertSize); |
| 606 } | 514 } |
| 607 } | 515 } |
| 608 fCurrVertex += 4; | 516 fCurrVertex += 4; |
| 609 } | 517 } |
| 518 |
| 519 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { |
| 520 unsigned r = SkColorGetR(c); |
| 521 unsigned g = SkColorGetG(c); |
| 522 unsigned b = SkColorGetB(c); |
| 523 return GrColorPackRGBA(r, g, b, 0xff); |
| 524 } |
| 525 |
| 526 void GrBitmapTextContext::flush() { |
| 527 if (NULL == fDrawTarget) { |
| 528 return; |
| 529 } |
| 530 |
| 531 GrDrawState* drawState = fDrawTarget->drawState(); |
| 532 GrDrawState::AutoRestoreEffects are(drawState); |
| 533 drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); |
| 534 |
| 535 if (fCurrVertex > 0) { |
| 536 // setup our sampler state for our text texture/atlas |
| 537 SkASSERT(SkIsAlign4(fCurrVertex)); |
| 538 SkASSERT(fCurrTexture); |
| 539 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon
e_FilterMode); |
| 540 |
| 541 uint32_t textureUniqueID = fCurrTexture->getUniqueID(); |
| 542 |
| 543 if (textureUniqueID != fEffectTextureUniqueID) { |
| 544 fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(f
CurrTexture, |
| 545 p
arams)); |
| 546 fEffectTextureUniqueID = textureUniqueID; |
| 547 } |
| 548 |
| 549 // This effect could be stored with one of the cache objects (atlas?) |
| 550 drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); |
| 551 SkASSERT(fStrike); |
| 552 switch (fStrike->getMaskFormat()) { |
| 553 // Color bitmap text |
| 554 case kARGB_GrMaskFormat: |
| 555 SkASSERT(!drawState->hasColorVertexAttribute()); |
| 556 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); |
| 557 drawState->setColor(0xffffffff); |
| 558 break; |
| 559 // LCD text |
| 560 case kA888_GrMaskFormat: |
| 561 case kA565_GrMaskFormat: { |
| 562 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || |
| 563 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || |
| 564 fPaint.numColorStages()) { |
| 565 GrPrintf("LCD Text will not draw correctly.\n"); |
| 566 } |
| 567 SkASSERT(!drawState->hasColorVertexAttribute()); |
| 568 // We don't use the GrPaint's color in this case because it's be
en premultiplied by |
| 569 // alpha. Instead we feed in a non-premultiplied color, and mult
iply its alpha by |
| 570 // the mask texture color. The end result is that we get |
| 571 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*d
stColor |
| 572 int a = SkColorGetA(fSkPaint.getColor()); |
| 573 // paintAlpha |
| 574 drawState->setColor(SkColorSetARGB(a, a, a, a)); |
| 575 // paintColor |
| 576 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSk
Paint.getColor())); |
| 577 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff)
; |
| 578 break; |
| 579 } |
| 580 // Grayscale/BW text |
| 581 case kA8_GrMaskFormat: |
| 582 // set back to normal in case we took LCD path previously. |
| 583 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); |
| 584 // We're using per-vertex color. |
| 585 SkASSERT(drawState->hasColorVertexAttribute()); |
| 586 break; |
| 587 default: |
| 588 SkFAIL("Unexepected mask format."); |
| 589 } |
| 590 int nGlyphs = fCurrVertex / 4; |
| 591 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
| 592 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, |
| 593 nGlyphs, |
| 594 4, 6, &fVertexBounds); |
| 595 |
| 596 fDrawTarget->resetVertexSource(); |
| 597 fVertices = NULL; |
| 598 fMaxVertices = 0; |
| 599 fCurrVertex = 0; |
| 600 fVertexBounds.setLargestInverted(); |
| 601 SkSafeSetNull(fCurrTexture); |
| 602 } |
| 603 } |
| 604 |
| 605 inline void GrBitmapTextContext::finish() { |
| 606 this->flush(); |
| 607 |
| 608 GrTextContext::finish(); |
| 609 } |
| 610 |
| OLD | NEW |