OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "GrStencilAndCoverTextContext.h" | 8 #include "GrStencilAndCoverTextContext.h" |
9 #include "GrAtlasTextContext.h" | 9 #include "GrAtlasTextContext.h" |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } | 335 } |
336 | 336 |
337 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 337 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
338 | 338 |
339 class GrStencilAndCoverTextContext::FallbackBlobBuilder { | 339 class GrStencilAndCoverTextContext::FallbackBlobBuilder { |
340 public: | 340 public: |
341 FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {} | 341 FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {} |
342 | 342 |
343 bool isInitialized() const { return fBuilder != nullptr; } | 343 bool isInitialized() const { return fBuilder != nullptr; } |
344 | 344 |
345 void init(const SkPaint& font, SkScalar textRatio); | 345 void init(sk_sp<SkFont> font, SkScalar textRatio); |
346 | 346 |
347 void appendGlyph(uint16_t glyphId, const SkPoint& pos); | 347 void appendGlyph(uint16_t glyphId, const SkPoint& pos); |
348 | 348 |
349 const SkTextBlob* buildIfNeeded(int* count); | 349 const SkTextBlob* buildIfNeeded(int* count); |
350 | 350 |
351 private: | 351 private: |
352 enum { kWriteBufferSize = 1024 }; | 352 enum { kWriteBufferSize = 1024 }; |
353 | 353 |
354 void flush(); | 354 void flush(); |
355 | 355 |
356 SkAutoTDelete<SkTextBlobBuilder> fBuilder; | 356 SkAutoTDelete<SkTextBlobBuilder> fBuilder; |
357 SkPaint fFont; | 357 SkPaint fFont; |
358 int fBuffIdx; | 358 int fBuffIdx; |
359 int fCount; | 359 int fCount; |
360 uint16_t fGlyphIds[kWriteBufferSize]; | 360 uint16_t fGlyphIds[kWriteBufferSize]; |
361 SkPoint fPositions[kWriteBufferSize]; | 361 SkPoint fPositions[kWriteBufferSize]; |
362 }; | 362 }; |
363 | 363 |
364 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 364 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
365 | 365 |
| 366 |
| 367 static sk_sp<SkFont> make_font_from_paint(const SkPaint& paint) { |
| 368 uint32_t flags = 0; |
| 369 if (paint.isVerticalText()) { |
| 370 flags |= SkFont::kVertical_Flag; |
| 371 } |
| 372 if (paint.isEmbeddedBitmapText()) { |
| 373 flags |= SkFont::kEmbeddedBitmaps_Flag; |
| 374 } |
| 375 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) { |
| 376 flags |= SkFont::kGenA8FromLCD_Flag; |
| 377 } |
| 378 if (paint.isFakeBoldText()) { |
| 379 flags |= SkFont::kEmbolden_Flag; |
| 380 } |
| 381 if (SkPaint::kFull_Hinting == paint.getHinting()) { |
| 382 flags |= SkFont::kEnableByteCodeHints_Flag; |
| 383 } |
| 384 if (paint.isAutohinted()) { |
| 385 flags |= SkFont::kEnableAutoHints_Flag; |
| 386 } |
| 387 if (paint.isSubpixelText() || paint.isLinearText()) { |
| 388 // this is our default |
| 389 } else { |
| 390 flags |= SkFont::kUseNonlinearMetrics_Flag; |
| 391 } |
| 392 if (paint.isDevKernText()) { |
| 393 flags |= SkFont::kDevKern_Flag; |
| 394 } |
| 395 |
| 396 SkFont::MaskType maskType = SkFont::kBW_MaskType; |
| 397 if (paint.isAntiAlias()) { |
| 398 maskType = paint.isLCDRenderText() ? SkFont::kLCD_MaskType : SkFont::kA8
_MaskType; |
| 399 } |
| 400 |
| 401 return SkFont::Make(sk_ref_sp(paint.getTypeface()), |
| 402 paint.getTextSize(), |
| 403 paint.getTextScaleX(), |
| 404 paint.getTextSkewX(), |
| 405 maskType, |
| 406 flags); |
| 407 } |
| 408 |
| 409 static SkTextEncoding from_paint_encoding(SkPaint::TextEncoding encoding) { |
| 410 static_assert(kUTF8_SkTextEncoding == SkPaint::kUTF8_TextEncoding, "enum mis
match"); |
| 411 static_assert(kUTF16_SkTextEncoding == SkPaint::kUTF16_TextEncoding, "enum m
ismatch"); |
| 412 static_assert(kUTF32_SkTextEncoding == SkPaint::kUTF32_TextEncoding, "enum m
ismatch"); |
| 413 static_assert(kGlyphID_SkTextEncoding == SkPaint::kGlyphID_TextEncoding, "en
um mismatch"); |
| 414 return (SkTextEncoding) encoding; |
| 415 } |
| 416 |
| 417 static SkPaint::TextEncoding from_font_encoding(SkTextEncoding encoding) { |
| 418 static_assert(kUTF8_SkTextEncoding == SkPaint::kUTF8_TextEncoding, "enum mis
match"); |
| 419 static_assert(kUTF16_SkTextEncoding == SkPaint::kUTF16_TextEncoding, "enum m
ismatch"); |
| 420 static_assert(kUTF32_SkTextEncoding == SkPaint::kUTF32_TextEncoding, "enum m
ismatch"); |
| 421 static_assert(kGlyphID_SkTextEncoding == SkPaint::kGlyphID_TextEncoding, "en
um mismatch"); |
| 422 return (SkPaint::TextEncoding) encoding; |
| 423 } |
| 424 |
366 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) | 425 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) |
367 : fStyle(fontAndStroke) | 426 : fStyle(fontAndStroke) |
368 , fFont(fontAndStroke) | |
369 , fTotalGlyphCount(0) | 427 , fTotalGlyphCount(0) |
370 , fFallbackGlyphCount(0) | 428 , fFallbackGlyphCount(0) |
371 , fDetachedGlyphCache(nullptr) | 429 , fDetachedGlyphCache(nullptr) |
372 , fLastDrawnGlyphsID(SK_InvalidUniqueID) { | 430 , fLastDrawnGlyphsID(SK_InvalidUniqueID) { |
373 SkASSERT(fFont.getTextSize() > 0); | |
374 SkASSERT(!fStyle.hasNonDashPathEffect()); // Arbitrary path effects not supp
orted. | 431 SkASSERT(!fStyle.hasNonDashPathEffect()); // Arbitrary path effects not supp
orted. |
375 SkASSERT(!fStyle.isSimpleHairline()); // Hairlines are not supported. | 432 SkASSERT(!fStyle.isSimpleHairline()); // Hairlines are not supported. |
376 | 433 |
377 // Setting to "fill" ensures that no strokes get baked into font outlines. (
We use the GPU path | |
378 // rendering API for stroking). | |
379 fFont.setStyle(SkPaint::kFill_Style); | |
380 | 434 |
381 if (fFont.isFakeBoldText() && fStyle.isSimpleFill()) { | 435 fFont = make_font_from_paint(fontAndStroke); |
| 436 SkASSERT(fFont->getSize() > 0); |
| 437 fTextEncoding = from_paint_encoding(fontAndStroke.getTextEncoding()); |
| 438 fTextAlign = fontAndStroke.getTextAlign(); |
| 439 |
| 440 if (fFont->isEmbolden() && fStyle.isSimpleFill()) { |
382 const SkStrokeRec& stroke = fStyle.strokeRec(); | 441 const SkStrokeRec& stroke = fStyle.strokeRec(); |
383 // Instead of letting fake bold get baked into the glyph outlines, do it
with GPU stroke. | 442 // Instead of letting fake bold get baked into the glyph outlines, do it
with GPU stroke. |
384 SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(), | 443 SkScalar fakeBoldScale = SkScalarInterpFunc(fFont->getSize(), |
385 kStdFakeBoldInterpKeys, | 444 kStdFakeBoldInterpKeys, |
386 kStdFakeBoldInterpValues, | 445 kStdFakeBoldInterpValues, |
387 kStdFakeBoldInterpLength); | 446 kStdFakeBoldInterpLength); |
388 SkScalar extra = SkScalarMul(fFont.getTextSize(), fakeBoldScale); | 447 SkScalar extra = SkScalarMul(fFont->getSize(), fakeBoldScale); |
389 | 448 |
390 SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); | 449 SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); |
391 strokeRec.setStrokeStyle(stroke.needToApply() ? stroke.getWidth() + extr
a : extra, | 450 strokeRec.setStrokeStyle(stroke.needToApply() ? stroke.getWidth() + extr
a : extra, |
392 true /*strokeAndFill*/); | 451 true /*strokeAndFill*/); |
393 fStyle = GrStyle(strokeRec, fStyle.pathEffect()); | 452 fStyle = GrStyle(strokeRec, fStyle.pathEffect()); |
394 fFont.setFakeBoldText(false); | 453 |
| 454 uint32_t newFlags = fFont->getFlags() & ~SkFont::kEmbolden_Flag; |
| 455 fFont = fFont->makeWithFlags(newFlags); |
395 } | 456 } |
396 | 457 |
397 if (!fFont.getPathEffect() && !fStyle.isDashed()) { | 458 if (!fStyle.pathEffect() && !fStyle.isDashed()) { |
398 const SkStrokeRec& stroke = fStyle.strokeRec(); | 459 const SkStrokeRec& stroke = fStyle.strokeRec(); |
399 // We can draw the glyphs from canonically sized paths. | 460 // We can draw the glyphs from canonically sized paths. |
400 fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; | 461 fTextRatio = fFont->getSize() / SkPaint::kCanonicalTextSizeForPaths; |
401 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextS
ize(); | 462 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont->getSize
(); |
402 | 463 |
403 // Compensate for the glyphs being scaled by fTextRatio. | 464 // Compensate for the glyphs being scaled by fTextRatio. |
404 if (!fStyle.isSimpleFill()) { | 465 if (!fStyle.isSimpleFill()) { |
405 SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); | 466 SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); |
406 strokeRec.setStrokeStyle(stroke.getWidth() / fTextRatio, | 467 strokeRec.setStrokeStyle(stroke.getWidth() / fTextRatio, |
407 SkStrokeRec::kStrokeAndFill_Style == stroke
.getStyle()); | 468 SkStrokeRec::kStrokeAndFill_Style == stroke
.getStyle()); |
408 fStyle = GrStyle(strokeRec, fStyle.pathEffect()); | 469 fStyle = GrStyle(strokeRec, fStyle.pathEffect()); |
409 } | 470 } |
410 | 471 |
411 fFont.setLinearText(true); | 472 uint32_t newFlags = fFont->getFlags(); |
412 fFont.setLCDRenderText(false); | 473 newFlags |= 0; |
413 fFont.setAutohinted(false); | 474 newFlags &= ~(SkFont::kEnableAutoHints_Flag|SkFont::kEnableByteCodeHints
_Flag| |
414 fFont.setHinting(SkPaint::kNo_Hinting); | 475 SkFont::kUseNonlinearMetrics_Flag); |
415 fFont.setSubpixelText(true); | |
416 fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); | |
417 | 476 |
418 fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() && | 477 fFont = SkFont::Make(sk_ref_sp(fFont->getTypeface()), |
419 0 == fFont.getTextSkewX() && | 478 SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths), |
420 !fFont.isFakeBoldText() && | 479 fFont->getScaleX(), |
421 !fFont.isVerticalText(); | 480 fFont->getSkewX(), |
| 481 fFont->getMaskType() == SkFont::kLCD_MaskType ? SkF
ont::kA8_MaskType |
| 482 : SkF
ont::kBW_MaskType, |
| 483 newFlags); |
| 484 |
| 485 fUsingRawGlyphPaths = SK_Scalar1 == fFont->getScaleX() && |
| 486 0 == fFont->getSkewX() && |
| 487 !fFont->isEmbolden() && |
| 488 !fFont->isVertical(); |
422 } else { | 489 } else { |
423 fTextRatio = fTextInverseRatio = 1.0f; | 490 fTextRatio = fTextInverseRatio = 1.0f; |
424 fUsingRawGlyphPaths = false; | 491 fUsingRawGlyphPaths = false; |
425 } | 492 } |
426 | 493 |
427 // Generate the key that will be used to cache the GPU glyph path objects. | 494 // Generate the key that will be used to cache the GPU glyph path objects. |
428 if (fUsingRawGlyphPaths && fStyle.isSimpleFill()) { | 495 if (fUsingRawGlyphPaths && fStyle.isSimpleFill()) { |
429 static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::
GenerateDomain(); | 496 static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::
GenerateDomain(); |
430 | 497 |
431 const SkTypeface* typeface = fFont.getTypeface(); | 498 const SkTypeface* typeface = fFont->getTypeface(); |
432 GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1
); | 499 GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1
); |
433 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID(
) : 0; | 500 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID(
) : 0; |
434 } else { | 501 } else { |
435 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::Generat
eDomain(); | 502 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::Generat
eDomain(); |
436 | 503 |
437 int styleDataCount = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffec
tAndStrokeRec); | 504 int styleDataCount = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffec
tAndStrokeRec); |
438 // Key should be valid since we opted out of drawing arbitrary path effe
cts. | 505 // Key should be valid since we opted out of drawing arbitrary path effe
cts. |
439 SkASSERT(styleDataCount >= 0); | 506 SkASSERT(styleDataCount >= 0); |
440 if (fUsingRawGlyphPaths) { | 507 if (fUsingRawGlyphPaths) { |
441 const SkTypeface* typeface = fFont.getTypeface(); | 508 const SkTypeface* typeface = fFont->getTypeface(); |
442 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 +
styleDataCount); | 509 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 +
styleDataCount); |
443 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu
eID() : 0; | 510 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu
eID() : 0; |
444 reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount; | 511 reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount; |
445 if (styleDataCount) { | 512 if (styleDataCount) { |
446 write_style_key(&builder[2], fStyle); | 513 write_style_key(&builder[2], fStyle); |
447 } | 514 } |
448 } else { | 515 } else { |
449 SkGlyphCache* glyphCache = this->getGlyphCache(); | 516 SkGlyphCache* glyphCache = this->getGlyphCache(); |
450 const SkTypeface* typeface = glyphCache->getScalerContext()->getType
face(); | 517 const SkTypeface* typeface = glyphCache->getScalerContext()->getType
face(); |
451 const SkDescriptor* desc = &glyphCache->getDescriptor(); | 518 const SkDescriptor* desc = &glyphCache->getDescriptor(); |
(...skipping 12 matching lines...) Expand all Loading... |
464 | 531 |
465 GrStencilAndCoverTextContext::TextRun::~TextRun() { | 532 GrStencilAndCoverTextContext::TextRun::~TextRun() { |
466 this->releaseGlyphCache(); | 533 this->releaseGlyphCache(); |
467 } | 534 } |
468 | 535 |
469 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
teLength, | 536 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
teLength, |
470 SkScalar x, SkScalar y) { | 537 SkScalar x, SkScalar y) { |
471 SkASSERT(byteLength == 0 || text != nullptr); | 538 SkASSERT(byteLength == 0 || text != nullptr); |
472 | 539 |
473 SkGlyphCache* glyphCache = this->getGlyphCache(); | 540 SkGlyphCache* glyphCache = this->getGlyphCache(); |
474 SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.ge
tTextEncoding(), | 541 SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(from_fon
t_encoding(fTextEncoding), |
475 fFont.is
DevKernText(), | 542 fFont->i
sDevKern(), |
476 true); | 543 true); |
477 | 544 |
478 fTotalGlyphCount = fFont.countText(text, byteLength); | 545 fTotalGlyphCount = fFont->countText(text, byteLength, fTextEncoding); |
479 fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTran
sformType, | 546 fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTran
sformType, |
480 fTotalGlyphCount)); | 547 fTotalGlyphCount)); |
481 | 548 |
482 const char* stop = text + byteLength; | 549 const char* stop = text + byteLength; |
483 | 550 |
484 // Measure first if needed. | 551 // Measure first if needed. |
485 if (fFont.getTextAlign() != SkPaint::kLeft_Align) { | 552 if (SkPaint::kLeft_Align != fTextAlign) { |
486 SkScalar stopX = 0; | 553 SkScalar stopX = 0; |
487 SkScalar stopY = 0; | 554 SkScalar stopY = 0; |
488 | 555 |
489 const char* textPtr = text; | 556 const char* textPtr = text; |
490 while (textPtr < stop) { | 557 while (textPtr < stop) { |
491 // We don't need x, y here, since all subpixel variants will have th
e | 558 // We don't need x, y here, since all subpixel variants will have th
e |
492 // same advance. | 559 // same advance. |
493 const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr); | 560 const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr); |
494 | 561 |
495 stopX += SkFloatToScalar(glyph.fAdvanceX); | 562 stopX += SkFloatToScalar(glyph.fAdvanceX); |
496 stopY += SkFloatToScalar(glyph.fAdvanceY); | 563 stopY += SkFloatToScalar(glyph.fAdvanceY); |
497 } | 564 } |
498 SkASSERT(textPtr == stop); | 565 SkASSERT(textPtr == stop); |
499 | 566 |
500 SkScalar alignX = stopX * fTextRatio; | 567 SkScalar alignX = stopX * fTextRatio; |
501 SkScalar alignY = stopY * fTextRatio; | 568 SkScalar alignY = stopY * fTextRatio; |
502 | 569 |
503 if (fFont.getTextAlign() == SkPaint::kCenter_Align) { | 570 if (SkPaint::kCenter_Align == fTextAlign) { |
504 alignX = SkScalarHalf(alignX); | 571 alignX = SkScalarHalf(alignX); |
505 alignY = SkScalarHalf(alignY); | 572 alignY = SkScalarHalf(alignY); |
506 } | 573 } |
507 | 574 |
508 x -= alignX; | 575 x -= alignX; |
509 y -= alignY; | 576 y -= alignY; |
510 } | 577 } |
511 | 578 |
512 SkAutoKern autokern; | 579 SkAutoKern autokern; |
513 | 580 |
(...skipping 12 matching lines...) Expand all Loading... |
526 fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); | 593 fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); |
527 } | 594 } |
528 | 595 |
529 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
byteLength, | 596 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
byteLength, |
530 const SkScalar pos[], int
scalarsPerPosition, | 597 const SkScalar pos[], int
scalarsPerPosition, |
531 const SkPoint& offset) { | 598 const SkPoint& offset) { |
532 SkASSERT(byteLength == 0 || text != nullptr); | 599 SkASSERT(byteLength == 0 || text != nullptr); |
533 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 600 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
534 | 601 |
535 SkGlyphCache* glyphCache = this->getGlyphCache(); | 602 SkGlyphCache* glyphCache = this->getGlyphCache(); |
536 SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.ge
tTextEncoding(), | 603 SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(from_fon
t_encoding(fTextEncoding), |
537 fFont.is
DevKernText(), | 604 fFont->i
sDevKern(), |
538 true); | 605 true); |
539 | 606 |
540 fTotalGlyphCount = fFont.countText(text, byteLength); | 607 fTotalGlyphCount = fFont->countText(text, byteLength, fTextEncoding); |
541 fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTran
sformType, | 608 fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTran
sformType, |
542 fTotalGlyphCount)); | 609 fTotalGlyphCount)); |
543 | 610 |
544 const char* stop = text + byteLength; | 611 const char* stop = text + byteLength; |
545 | 612 |
546 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); | 613 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); |
547 SkTextAlignProc alignProc(fFont.getTextAlign()); | 614 SkTextAlignProc alignProc(fTextAlign); |
548 FallbackBlobBuilder fallback; | 615 FallbackBlobBuilder fallback; |
549 while (text < stop) { | 616 while (text < stop) { |
550 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text); | 617 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text); |
551 if (glyph.fWidth) { | 618 if (glyph.fWidth) { |
552 SkPoint tmsLoc; | 619 SkPoint tmsLoc; |
553 tmsProc(pos, &tmsLoc); | 620 tmsProc(pos, &tmsLoc); |
554 SkPoint loc; | 621 SkPoint loc; |
555 alignProc(tmsLoc, glyph, &loc); | 622 alignProc(tmsLoc, glyph, &loc); |
556 | 623 |
557 this->appendGlyph(glyph, loc, &fallback); | 624 this->appendGlyph(glyph, loc, &fallback); |
558 } | 625 } |
559 pos += scalarsPerPosition; | 626 pos += scalarsPerPosition; |
560 } | 627 } |
561 | 628 |
562 fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); | 629 fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); |
563 } | 630 } |
564 | 631 |
565 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx)
const { | 632 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx)
const { |
566 GrPathRange* glyphs = static_cast<GrPathRange*>( | 633 GrPathRange* glyphs = static_cast<GrPathRange*>( |
567 ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKe
y)); | 634 ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKe
y)); |
568 if (nullptr == glyphs) { | 635 if (nullptr == glyphs) { |
569 if (fUsingRawGlyphPaths) { | 636 if (fUsingRawGlyphPaths) { |
570 SkScalerContextEffects noeffects; | 637 SkScalerContextEffects noeffects; |
571 glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(),
noeffects, | 638 glyphs = ctx->resourceProvider()->createGlyphs(fFont->getTypeface(),
noeffects, |
572 nullptr, fStyle); | 639 nullptr, fStyle); |
573 } else { | 640 } else { |
574 SkGlyphCache* cache = this->getGlyphCache(); | 641 SkGlyphCache* cache = this->getGlyphCache(); |
575 glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerConte
xt()->getTypeface(), | 642 glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerConte
xt()->getTypeface(), |
576 cache->getScalerConte
xt()->getEffects(), | 643 cache->getScalerConte
xt()->getEffects(), |
577 &cache->getDescriptor
(), | 644 &cache->getDescriptor
(), |
578 fStyle); | 645 fStyle); |
579 } | 646 } |
580 ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyph
s); | 647 ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyph
s); |
581 } | 648 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 fLastDrawnGlyphsID = glyphs->getUniqueID(); | 695 fLastDrawnGlyphsID = glyphs->getUniqueID(); |
629 } | 696 } |
630 | 697 |
631 // Don't compute a bounding box. For dst copy texture, we'll opt instead
for it to just copy | 698 // Don't compute a bounding box. For dst copy texture, we'll opt instead
for it to just copy |
632 // the entire dst. Realistically this is a moot point, because any conte
xt that supports | 699 // the entire dst. Realistically this is a moot point, because any conte
xt that supports |
633 // NV_path_rendering will also support NV_blend_equation_advanced. | 700 // NV_path_rendering will also support NV_blend_equation_advanced. |
634 // For clipping we'll just skip any optimizations based on the bounds. T
his does, however, | 701 // For clipping we'll just skip any optimizations based on the bounds. T
his does, however, |
635 // hurt batching. | 702 // hurt batching. |
636 const SkRect bounds = SkRect::MakeIWH(drawContext->width(), drawContext-
>height()); | 703 const SkRect bounds = SkRect::MakeIWH(drawContext->width(), drawContext-
>height()); |
637 | 704 |
| 705 GrColor color = grPaint.getColor(); |
| 706 |
638 SkAutoTUnref<GrDrawBatch> batch( | 707 SkAutoTUnref<GrDrawBatch> batch( |
639 GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRat
io * x, | 708 GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRat
io * x, |
640 fTextInverseRatio * y, grPaint.getColor
(), | 709 fTextInverseRatio * y, color, |
641 GrPathRendering::kWinding_FillType, gly
phs, fInstanceData, | 710 GrPathRendering::kWinding_FillType, gly
phs, fInstanceData, |
642 bounds)); | 711 bounds)); |
643 | 712 |
644 GrPipelineBuilder pipelineBuilder(grPaint); | 713 GrPipelineBuilder pipelineBuilder(grPaint); |
645 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, grPaint.i
sAntiAlias()); | 714 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, grPaint.i
sAntiAlias()); |
646 pipelineBuilder.setUserStencil(&kCoverPass); | 715 pipelineBuilder.setUserStencil(&kCoverPass); |
647 | 716 |
648 drawContext->drawBatch(pipelineBuilder, clip, batch); | 717 drawContext->drawBatch(pipelineBuilder, clip, batch); |
649 } | 718 } |
650 | 719 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 size += sizeof(InstanceData); | 753 size += sizeof(InstanceData); |
685 } | 754 } |
686 if (fFallbackTextBlob) { | 755 if (fFallbackTextBlob) { |
687 size += sizeof(SkTextBlob); | 756 size += sizeof(SkTextBlob); |
688 } | 757 } |
689 return size; | 758 return size; |
690 } | 759 } |
691 | 760 |
692 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 761 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
693 | 762 |
694 void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font
, | 763 void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(sk_sp<SkFont> font, |
695 SkScalar textRatio)
{ | 764 SkScalar textRatio)
{ |
696 SkASSERT(!this->isInitialized()); | 765 SkASSERT(!this->isInitialized()); |
697 fBuilder.reset(new SkTextBlobBuilder); | 766 fBuilder.reset(new SkTextBlobBuilder); |
698 fFont = font; | 767 |
699 fFont.setTextAlign(SkPaint::kLeft_Align); // The glyph positions will alread
y account for align. | 768 // The Fallback path still uses a full SkPaint! |
700 fFont.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 769 // fTextAlign = SkPaint::kLeft_Align; // The glyph positions will already acc
ount for align. |
| 770 // fTextEncoding = SkPaint::kGlyphID_TextEncoding; |
701 // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non
-bitmap color glyphs | 771 // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non
-bitmap color glyphs |
702 // show up and https://code.google.com/p/skia/issues/detail?id=4408 gets res
olved. | 772 // show up and https://code.google.com/p/skia/issues/detail?id=4408 gets res
olved. |
703 fFont.setSubpixelText(false); | 773 #if 0 |
704 fFont.setTextSize(fFont.getTextSize() * textRatio); | 774 fFont = SkFont::Make(sk_ref_sp(font->getTypeface()), |
| 775 font->getSize() * textRatio, |
| 776 font->getScaleX(), |
| 777 font->getSkewX(), |
| 778 font->getMaskType(), |
| 779 font->getFlags() & ~SkFont::kUseNonlinearMetrics_Flag); |
| 780 #endif |
705 fBuffIdx = 0; | 781 fBuffIdx = 0; |
706 } | 782 } |
707 | 783 |
708 void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t gly
phId, | 784 void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t gly
phId, |
709 const SkPoin
t& pos) { | 785 const SkPoin
t& pos) { |
710 SkASSERT(this->isInitialized()); | 786 SkASSERT(this->isInitialized()); |
711 if (fBuffIdx >= kWriteBufferSize) { | 787 if (fBuffIdx >= kWriteBufferSize) { |
712 this->flush(); | 788 this->flush(); |
713 } | 789 } |
714 fGlyphIds[fBuffIdx] = glyphId; | 790 fGlyphIds[fBuffIdx] = glyphId; |
(...skipping 16 matching lines...) Expand all Loading... |
731 } | 807 } |
732 | 808 |
733 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeed
ed(int *count) { | 809 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeed
ed(int *count) { |
734 *count = fCount; | 810 *count = fCount; |
735 if (fCount) { | 811 if (fCount) { |
736 this->flush(); | 812 this->flush(); |
737 return fBuilder->build(); | 813 return fBuilder->build(); |
738 } | 814 } |
739 return nullptr; | 815 return nullptr; |
740 } | 816 } |
OLD | NEW |