OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 #ifndef SkFindAndPositionGlyph_DEFINED | 8 #ifndef SkFindAndPositionGlyph_DEFINED |
9 #define SkFindAndPositionGlyph_DEFINED | 9 #define SkFindAndPositionGlyph_DEFINED |
10 | 10 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 | 340 |
341 typedef PolymorphicVariant< | 341 typedef PolymorphicVariant< |
342 MapperInterface, TranslationMapper, XScaleMapper, GeneralMapper> Mapper; | 342 MapperInterface, TranslationMapper, XScaleMapper, GeneralMapper> Mapper; |
343 | 343 |
344 // TextAlignmentAdjustment handles shifting the glyph based on its width. | 344 // TextAlignmentAdjustment handles shifting the glyph based on its width. |
345 static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const S
kGlyph& glyph) { | 345 static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const S
kGlyph& glyph) { |
346 switch (textAlignment) { | 346 switch (textAlignment) { |
347 case SkPaint::kLeft_Align: | 347 case SkPaint::kLeft_Align: |
348 return {0.0f, 0.0f}; | 348 return {0.0f, 0.0f}; |
349 case SkPaint::kCenter_Align: | 349 case SkPaint::kCenter_Align: |
350 return {SkFixedToScalar(glyph.fAdvanceX >> 1), | 350 return {SkFloatToScalar(glyph.fAdvanceX) / 2, |
351 SkFixedToScalar(glyph.fAdvanceY >> 1)}; | 351 SkFloatToScalar(glyph.fAdvanceY) / 2}; |
352 case SkPaint::kRight_Align: | 352 case SkPaint::kRight_Align: |
353 return {SkFixedToScalar(glyph.fAdvanceX), | 353 return {SkFloatToScalar(glyph.fAdvanceX), |
354 SkFixedToScalar(glyph.fAdvanceY)}; | 354 SkFloatToScalar(glyph.fAdvanceY)}; |
355 } | 355 } |
356 // Even though the entire enum is covered above, MVSC doesn't think so.
Make it happy. | 356 // Even though the entire enum is covered above, MVSC doesn't think so.
Make it happy. |
357 SkFAIL("Should never get here."); | 357 SkFAIL("Should never get here."); |
358 return {0.0f, 0.0f}; | 358 return {0.0f, 0.0f}; |
359 } | 359 } |
360 | 360 |
361 // The "call" to SkFixedToScalar is actually a macro. It's macros all the wa
y down. | 361 // The "call" to SkFixedToScalar is actually a macro. It's macros all the wa
y down. |
362 // Needs to be a macro because you can't have a const float unless you make
it constexpr. | 362 // Needs to be a macro because you can't have a const float unless you make
it constexpr. |
363 #define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound)) | 363 #define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound)) |
364 | 364 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 if (kTextAlignment != SkPaint::kLeft_Align) { | 440 if (kTextAlignment != SkPaint::kLeft_Align) { |
441 // Get the width of an un-sub-pixel positioned glyph for calcula
ting the | 441 // Get the width of an un-sub-pixel positioned glyph for calcula
ting the |
442 // alignment. This is not needed for kLeftAlign because its adju
stment is | 442 // alignment. This is not needed for kLeftAlign because its adju
stment is |
443 // always {0, 0}. | 443 // always {0, 0}. |
444 const char* tempText = *text; | 444 const char* tempText = *text; |
445 const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText
); | 445 const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText
); |
446 | 446 |
447 if (metricGlyph.fWidth <= 0) { | 447 if (metricGlyph.fWidth <= 0) { |
448 // Exiting early, be sure to update text pointer. | 448 // Exiting early, be sure to update text pointer. |
449 *text = tempText; | 449 *text = tempText; |
450 return finalPosition + SkPoint{SkFixedToScalar(metricGlyph.f
AdvanceX), | 450 return finalPosition + SkPoint{SkFloatToScalar(metricGlyph.f
AdvanceX), |
451 SkFixedToScalar(metricGlyph.f
AdvanceY)}; | 451 SkFloatToScalar(metricGlyph.f
AdvanceY)}; |
452 } | 452 } |
453 | 453 |
454 // Adjust the final position by the alignment adjustment. | 454 // Adjust the final position by the alignment adjustment. |
455 finalPosition -= TextAlignmentAdjustment(kTextAlignment, metricG
lyph); | 455 finalPosition -= TextAlignmentAdjustment(kTextAlignment, metricG
lyph); |
456 } | 456 } |
457 | 457 |
458 // Find the glyph. | 458 // Find the glyph. |
459 SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPos
ition); | 459 SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPos
ition); |
460 const SkGlyph& renderGlyph = | 460 const SkGlyph& renderGlyph = |
461 fGlyphFinder->lookupGlyphXY(text, lookupPosition.fX, lookupPosit
ion.fY); | 461 fGlyphFinder->lookupGlyphXY(text, lookupPosition.fX, lookupPosit
ion.fY); |
462 | 462 |
463 // If the glyph has no width (no pixels) then don't bother processin
g it. | 463 // If the glyph has no width (no pixels) then don't bother processin
g it. |
464 if (renderGlyph.fWidth > 0) { | 464 if (renderGlyph.fWidth > 0) { |
465 processOneGlyph(renderGlyph, finalPosition, | 465 processOneGlyph(renderGlyph, finalPosition, |
466 SubpixelPositionRounding(kAxisAlignment)); | 466 SubpixelPositionRounding(kAxisAlignment)); |
467 } | 467 } |
468 return finalPosition + SkPoint{SkFixedToScalar(renderGlyph.fAdvanceX
), | 468 return finalPosition + SkPoint{SkFloatToScalar(renderGlyph.fAdvanceX
), |
469 SkFixedToScalar(renderGlyph.fAdvanceY
)}; | 469 SkFloatToScalar(renderGlyph.fAdvanceY
)}; |
470 } | 470 } |
471 | 471 |
472 private: | 472 private: |
473 LookupGlyph& fGlyphFinder; | 473 LookupGlyph& fGlyphFinder; |
474 }; | 474 }; |
475 | 475 |
476 enum SelectKerning { | 476 enum SelectKerning { |
477 kNoKerning = false, | 477 kNoKerning = false, |
478 kUseKerning = true | 478 kUseKerning = true |
479 }; | 479 }; |
(...skipping 10 matching lines...) Expand all Loading... |
490 // Kerning can only be used with SkPaint::kLeft_Align | 490 // Kerning can only be used with SkPaint::kLeft_Align |
491 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment
, | 491 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment
, |
492 "Kerning can only be used with left aligned text."); | 492 "Kerning can only be used with left aligned text."); |
493 } | 493 } |
494 | 494 |
495 SkPoint findAndPositionGlyph( | 495 SkPoint findAndPositionGlyph( |
496 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly
ph) override { | 496 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly
ph) override { |
497 SkPoint finalPosition = position; | 497 SkPoint finalPosition = position; |
498 const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text); | 498 const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text); |
499 if (kUseKerning) { | 499 if (kUseKerning) { |
500 finalPosition += {SkFixedToScalar(fAutoKern.adjust(glyph)), 0.0f
}; | 500 finalPosition += {fAutoKern.adjust(glyph), 0.0f}; |
501 } | 501 } |
502 if (glyph.fWidth > 0) { | 502 if (glyph.fWidth > 0) { |
503 finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph); | 503 finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph); |
504 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarH
alf}); | 504 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarH
alf}); |
505 } | 505 } |
506 return finalPosition + SkPoint{SkFixedToScalar(glyph.fAdvanceX), | 506 return finalPosition + SkPoint{SkFloatToScalar(glyph.fAdvanceX), |
507 SkFixedToScalar(glyph.fAdvanceY)}; | 507 SkFloatToScalar(glyph.fAdvanceY)}; |
508 } | 508 } |
509 | 509 |
510 private: | 510 private: |
511 LookupGlyph& fGlyphFinder; | 511 LookupGlyph& fGlyphFinder; |
512 | 512 |
513 SkAutoKern fAutoKern; | 513 SkAutoKern fAutoKern; |
514 }; | 514 }; |
515 | 515 |
516 // GlyphFindAndPlace is a large variant that encapsulates the multiple types
of finding and | 516 // GlyphFindAndPlace is a large variant that encapsulates the multiple types
of finding and |
517 // placing a glyph. There are three factors that go into the different facto
rs. | 517 // placing a glyph. There are three factors that go into the different facto
rs. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(gly
phFinder); | 557 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(gly
phFinder); |
558 break; | 558 break; |
559 case kY_SkAxisAlignment: | 559 case kY_SkAxisAlignment: |
560 to_init->template initialize<GlyphFindAndPlaceSubpixel< | 560 to_init->template initialize<GlyphFindAndPlaceSubpixel< |
561 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(glyphF
inder); | 561 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(glyphF
inder); |
562 break; | 562 break; |
563 } | 563 } |
564 } | 564 } |
565 | 565 |
566 static SkPoint MeasureText(LookupGlyph& glyphFinder, const char text[], size
_t byteLength) { | 566 static SkPoint MeasureText(LookupGlyph& glyphFinder, const char text[], size
_t byteLength) { |
567 SkFixed x = 0, y = 0; | 567 SkScalar x = 0, y = 0; |
568 const char* stop = text + byteLength; | 568 const char* stop = text + byteLength; |
569 | 569 |
570 SkAutoKern autokern; | 570 SkAutoKern autokern; |
571 | 571 |
572 while (text < stop) { | 572 while (text < stop) { |
573 // don't need x, y here, since all subpixel variants will have the | 573 // don't need x, y here, since all subpixel variants will have the |
574 // same advance | 574 // same advance |
575 const SkGlyph& glyph = glyphFinder->lookupGlyph(&text); | 575 const SkGlyph& glyph = glyphFinder->lookupGlyph(&text); |
576 | 576 |
577 x += autokern.adjust(glyph) + glyph.fAdvanceX; | 577 x += autokern.adjust(glyph) + SkFloatToScalar(glyph.fAdvanceX); |
578 y += glyph.fAdvanceY; | 578 y += SkFloatToScalar(glyph.fAdvanceY); |
579 } | 579 } |
580 SkASSERT(text == stop); | 580 SkASSERT(text == stop); |
581 return {SkFixedToScalar(x), SkFixedToScalar(y)}; | 581 return {x, y}; |
582 } | 582 } |
583 }; | 583 }; |
584 | 584 |
585 template<typename ProcessOneGlyph> | 585 template<typename ProcessOneGlyph> |
586 inline void SkFindAndPlaceGlyph::ProcessPosText( | 586 inline void SkFindAndPlaceGlyph::ProcessPosText( |
587 SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength, | 587 SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength, |
588 SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPer
Position, | 588 SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPer
Position, |
589 SkPaint::Align textAlignment, | 589 SkPaint::Align textAlignment, |
590 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) { | 590 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) { |
591 | 591 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 SkPoint current = offset; | 727 SkPoint current = offset; |
728 while (text < stop) { | 728 while (text < stop) { |
729 current = | 729 current = |
730 findAndPosition->findAndPositionGlyph( | 730 findAndPosition->findAndPositionGlyph( |
731 &text, current, std::forward<ProcessOneGlyph>(processOneGlyph)); | 731 &text, current, std::forward<ProcessOneGlyph>(processOneGlyph)); |
732 | 732 |
733 } | 733 } |
734 } | 734 } |
735 | 735 |
736 #endif // SkFindAndPositionGlyph_DEFINED | 736 #endif // SkFindAndPositionGlyph_DEFINED |
OLD | NEW |