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 |