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 "GrDistanceFieldTextContext.h" | 8 #include "GrDistanceFieldTextContext.h" |
9 #include "GrAtlas.h" | 9 #include "GrAtlas.h" |
10 #include "GrBitmapTextContext.h" | 10 #include "GrBitmapTextContext.h" |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 | 287 |
288 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 288 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
289 | 289 |
290 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); | 290 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); |
291 SkGlyphCache* cache = autoCache.getCache(); | 291 SkGlyphCache* cache = autoCache.getCache(); |
292 GrFontScaler* fontScaler = GetGrFontScaler(cache); | 292 GrFontScaler* fontScaler = GetGrFontScaler(cache); |
293 | 293 |
294 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); | 294 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); |
295 | 295 |
296 const char* stop = text + byteLength; | 296 const char* stop = text + byteLength; |
| 297 SkTArray<char> fallbackTxt; |
| 298 SkTArray<SkScalar> fallbackPos; |
297 | 299 |
298 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 300 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
299 while (text < stop) { | 301 while (text < stop) { |
| 302 const char* lastText = text; |
300 // the last 2 parameters are ignored | 303 // the last 2 parameters are ignored |
301 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 304 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
302 | 305 |
303 if (glyph.fWidth) { | 306 if (glyph.fWidth) { |
304 SkScalar x = offset.x() + pos[0]; | 307 SkScalar x = offset.x() + pos[0]; |
305 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0)
; | 308 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0)
; |
306 | 309 |
307 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 310 if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
308 glyph.getSubXFixed(), | 311 glyph.getSubXFixed(), |
309 glyph.getSubYFixed()), | 312 glyph.getSubYFixed()), |
310 SkScalarToFixed(x), | 313 SkScalarToFixed(x), |
311 SkScalarToFixed(y), | 314 SkScalarToFixed(y), |
312 fontScaler); | 315 fontScaler)) { |
| 316 // couldn't append, send to fallback |
| 317 fallbackTxt.push_back_n(text-lastText, lastText); |
| 318 fallbackPos.push_back(pos[0]); |
| 319 if (2 == scalarsPerPosition) { |
| 320 fallbackPos.push_back(pos[1]); |
| 321 } |
| 322 } |
313 } | 323 } |
314 pos += scalarsPerPosition; | 324 pos += scalarsPerPosition; |
315 } | 325 } |
316 } else { | 326 } else { |
317 SkScalar alignMul = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ?
SK_ScalarHalf | 327 SkScalar alignMul = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ?
SK_ScalarHalf |
318 :
SK_Scalar1; | 328 :
SK_Scalar1; |
319 while (text < stop) { | 329 while (text < stop) { |
| 330 const char* lastText = text; |
320 // the last 2 parameters are ignored | 331 // the last 2 parameters are ignored |
321 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 332 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
322 | 333 |
323 if (glyph.fWidth) { | 334 if (glyph.fWidth) { |
324 SkScalar x = offset.x() + pos[0]; | 335 SkScalar x = offset.x() + pos[0]; |
325 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0)
; | 336 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0)
; |
326 | 337 |
327 SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX)*alignMul*fT
extRatio; | 338 SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX)*alignMul*fT
extRatio; |
328 SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY)*alignMul*fT
extRatio; | 339 SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY)*alignMul*fT
extRatio; |
329 | 340 |
330 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 341 if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
331 glyph.getSubXFixed(), | 342 glyph.getSubXFixed(), |
332 glyph.getSubYFixed()), | 343 glyph.getSubYFixed()), |
333 SkScalarToFixed(x - advanceX), | 344 SkScalarToFixed(x - advanceX), |
334 SkScalarToFixed(y - advanceY), | 345 SkScalarToFixed(y - advanceY), |
335 fontScaler); | 346 fontScaler)) { |
| 347 // couldn't append, send to fallback |
| 348 fallbackTxt.push_back_n(text-lastText, lastText); |
| 349 fallbackPos.push_back(pos[0]); |
| 350 if (2 == scalarsPerPosition) { |
| 351 fallbackPos.push_back(pos[1]); |
| 352 } |
| 353 } |
336 } | 354 } |
337 pos += scalarsPerPosition; | 355 pos += scalarsPerPosition; |
338 } | 356 } |
339 } | 357 } |
340 | 358 |
341 this->finish(); | 359 this->finish(); |
| 360 |
| 361 if (fallbackTxt.count() > 0) { |
| 362 fFallbackTextContext->drawPosText(paint, skPaint, fallbackTxt.begin(), f
allbackTxt.count(), |
| 363 fallbackPos.begin(), scalarsPerPositio
n, offset); |
| 364 } |
342 } | 365 } |
343 | 366 |
344 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { | 367 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { |
345 unsigned r = SkColorGetR(c); | 368 unsigned r = SkColorGetR(c); |
346 unsigned g = SkColorGetG(c); | 369 unsigned g = SkColorGetG(c); |
347 unsigned b = SkColorGetB(c); | 370 unsigned b = SkColorGetB(c); |
348 return GrColorPackRGBA(r, g, b, 0xff); | 371 return GrColorPackRGBA(r, g, b, 0xff); |
349 } | 372 } |
350 | 373 |
351 void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo
r) { | 374 void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo
r) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391
params, flags)); | 414
params, flags)); |
392 #endif | 415 #endif |
393 } | 416 } |
394 fEffectTextureUniqueID = textureUniqueID; | 417 fEffectTextureUniqueID = textureUniqueID; |
395 fEffectColor = filteredColor; | 418 fEffectColor = filteredColor; |
396 fEffectFlags = flags; | 419 fEffectFlags = flags; |
397 } | 420 } |
398 | 421 |
399 } | 422 } |
400 | 423 |
401 void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, | 424 // Returns true if this method handled the glyph, false if needs to be passed to
fallback |
| 425 // |
| 426 bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, |
402 SkFixed vx, SkFixed vy, | 427 SkFixed vx, SkFixed vy, |
403 GrFontScaler* scaler) { | 428 GrFontScaler* scaler) { |
404 if (NULL == fDrawTarget) { | 429 if (NULL == fDrawTarget) { |
405 return; | 430 return true; |
406 } | 431 } |
407 | 432 |
408 if (NULL == fStrike) { | 433 if (NULL == fStrike) { |
409 fStrike = fContext->getFontCache()->getStrike(scaler, true); | 434 fStrike = fContext->getFontCache()->getStrike(scaler, true); |
410 } | 435 } |
411 | 436 |
412 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); | 437 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); |
413 if (NULL == glyph || glyph->fBounds.isEmpty()) { | 438 if (NULL == glyph || glyph->fBounds.isEmpty()) { |
414 return; | 439 return true; |
415 } | 440 } |
416 | 441 |
417 // TODO: support color glyphs | 442 // fallback to color glyph support |
418 if (kA8_GrMaskFormat != glyph->fMaskFormat) { | 443 if (kA8_GrMaskFormat != glyph->fMaskFormat) { |
419 return; | 444 return false; |
420 } | 445 } |
421 | 446 |
422 SkScalar sx = SkFixedToScalar(vx); | 447 SkScalar sx = SkFixedToScalar(vx); |
423 SkScalar sy = SkFixedToScalar(vy); | 448 SkScalar sy = SkFixedToScalar(vy); |
424 /* | 449 /* |
425 // not valid, need to find a different solution for this | 450 // not valid, need to find a different solution for this |
426 vx += SkIntToFixed(glyph->fBounds.fLeft); | 451 vx += SkIntToFixed(glyph->fBounds.fLeft); |
427 vy += SkIntToFixed(glyph->fBounds.fTop); | 452 vy += SkIntToFixed(glyph->fBounds.fTop); |
428 | 453 |
429 // keep them as ints until we've done the clip-test | 454 // keep them as ints until we've done the clip-test |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 fStrike->addGlyphToAtlas(glyph, scaler)) { | 492 fStrike->addGlyphToAtlas(glyph, scaler)) { |
468 goto HAS_ATLAS; | 493 goto HAS_ATLAS; |
469 } | 494 } |
470 } | 495 } |
471 | 496 |
472 if (NULL == glyph->fPath) { | 497 if (NULL == glyph->fPath) { |
473 SkPath* path = SkNEW(SkPath); | 498 SkPath* path = SkNEW(SkPath); |
474 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { | 499 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { |
475 // flag the glyph as being dead? | 500 // flag the glyph as being dead? |
476 delete path; | 501 delete path; |
477 return; | 502 return true; |
478 } | 503 } |
479 glyph->fPath = path; | 504 glyph->fPath = path; |
480 } | 505 } |
481 | 506 |
482 // flush any accumulated draws before drawing this glyph as a path. | 507 // flush any accumulated draws before drawing this glyph as a path. |
483 this->flush(); | 508 this->flush(); |
484 | 509 |
485 GrContext::AutoMatrix am; | 510 GrContext::AutoMatrix am; |
486 SkMatrix ctm; | 511 SkMatrix ctm; |
487 ctm.setScale(fTextRatio, fTextRatio); | 512 ctm.setScale(fTextRatio, fTextRatio); |
488 ctm.postTranslate(sx, sy); | 513 ctm.postTranslate(sx, sy); |
489 GrPaint tmpPaint(fPaint); | 514 GrPaint tmpPaint(fPaint); |
490 am.setPreConcat(fContext, ctm, &tmpPaint); | 515 am.setPreConcat(fContext, ctm, &tmpPaint); |
491 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); | 516 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); |
492 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); | 517 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); |
493 return; | 518 return true; |
494 } | 519 } |
495 | 520 |
496 HAS_ATLAS: | 521 HAS_ATLAS: |
497 SkASSERT(glyph->fPlot); | 522 SkASSERT(glyph->fPlot); |
498 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); | 523 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); |
499 glyph->fPlot->setDrawToken(drawToken); | 524 glyph->fPlot->setDrawToken(drawToken); |
500 | 525 |
501 GrTexture* texture = glyph->fPlot->texture(); | 526 GrTexture* texture = glyph->fPlot->texture(); |
502 SkASSERT(texture); | 527 SkASSERT(texture); |
503 | 528 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 } | 624 } |
600 // color comes after position. | 625 // color comes after position. |
601 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); | 626 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); |
602 for (int i = 0; i < 4; ++i) { | 627 for (int i = 0; i < 4; ++i) { |
603 *colors = fPaint.getColor(); | 628 *colors = fPaint.getColor(); |
604 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(color
s) + vertSize); | 629 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(color
s) + vertSize); |
605 } | 630 } |
606 } | 631 } |
607 | 632 |
608 fCurrVertex += 4; | 633 fCurrVertex += 4; |
| 634 |
| 635 return true; |
609 } | 636 } |
610 | 637 |
611 void GrDistanceFieldTextContext::flush() { | 638 void GrDistanceFieldTextContext::flush() { |
612 if (NULL == fDrawTarget) { | 639 if (NULL == fDrawTarget) { |
613 return; | 640 return; |
614 } | 641 } |
615 | 642 |
616 GrDrawState* drawState = fDrawTarget->drawState(); | 643 GrDrawState* drawState = fDrawTarget->drawState(); |
617 GrDrawState::AutoRestoreEffects are(drawState); | 644 GrDrawState::AutoRestoreEffects are(drawState); |
618 | 645 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 fVertexBounds.setLargestInverted(); | 700 fVertexBounds.setLargestInverted(); |
674 } | 701 } |
675 } | 702 } |
676 | 703 |
677 inline void GrDistanceFieldTextContext::finish() { | 704 inline void GrDistanceFieldTextContext::finish() { |
678 this->flush(); | 705 this->flush(); |
679 | 706 |
680 GrTextContext::finish(); | 707 GrTextContext::finish(); |
681 } | 708 } |
682 | 709 |
OLD | NEW |