| 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 |