| 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 12 matching lines...) Expand all Loading... |
| 23 struct SkMaxSizeOf<> { | 23 struct SkMaxSizeOf<> { |
| 24 static const size_t value = 0; | 24 static const size_t value = 0; |
| 25 }; | 25 }; |
| 26 | 26 |
| 27 template<typename H, typename... Ts> | 27 template<typename H, typename... Ts> |
| 28 struct SkMaxSizeOf<H, Ts...> { | 28 struct SkMaxSizeOf<H, Ts...> { |
| 29 static const size_t value = | 29 static const size_t value = |
| 30 sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>:
:value; | 30 sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>:
:value; |
| 31 }; | 31 }; |
| 32 | 32 |
| 33 |
| 34 // This is a temporary helper function to work around a bug in the code generati
on |
| 35 // for aarch64 (arm) on GCC 4.9. This bug does not show up on other platforms, s
o it |
| 36 // seems to be an aarch64 backend problem. |
| 37 // |
| 38 // GCC 4.9 on ARM64 does not generate the proper constructor code for PositionRe
ader or |
| 39 // GlyphFindAndPlace. The vtable is not set properly without adding the fixme co
de. |
| 40 // The implementation is in SkDraw.cpp. |
| 41 extern void FixGCC49Arm64Bug(int v); |
| 42 |
| 33 class SkFindAndPlaceGlyph { | 43 class SkFindAndPlaceGlyph { |
| 34 public: | 44 public: |
| 35 template<typename ProcessOneGlyph> | 45 template<typename ProcessOneGlyph> |
| 36 static void ProcessText( | 46 static void ProcessText( |
| 37 SkPaint::TextEncoding, const char text[], size_t byteLength, | 47 SkPaint::TextEncoding, const char text[], size_t byteLength, |
| 38 SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment, | 48 SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment, |
| 39 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph); | 49 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph); |
| 40 // ProcessPosText handles all cases for finding and positioning glyphs. It h
as a very large | 50 // ProcessPosText handles all cases for finding and positioning glyphs. It h
as a very large |
| 41 // multiplicity. It figures out the glyph, position and rounding and pass th
ose parameters to | 51 // multiplicity. It figures out the glyph, position and rounding and pass th
ose parameters to |
| 42 // processOneGlyph. | 52 // processOneGlyph. |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 ) { } | 232 ) { } |
| 223 }; | 233 }; |
| 224 | 234 |
| 225 // PositionReaderInterface reads a point from the pos vector. | 235 // PositionReaderInterface reads a point from the pos vector. |
| 226 // * HorizontalPositions - assumes a common Y for many X values. | 236 // * HorizontalPositions - assumes a common Y for many X values. |
| 227 // * ArbitraryPositions - a list of (X,Y) pairs. | 237 // * ArbitraryPositions - a list of (X,Y) pairs. |
| 228 class PositionReaderInterface { | 238 class PositionReaderInterface { |
| 229 public: | 239 public: |
| 230 virtual ~PositionReaderInterface() { } | 240 virtual ~PositionReaderInterface() { } |
| 231 virtual SkPoint nextPoint() = 0; | 241 virtual SkPoint nextPoint() = 0; |
| 242 // This is only here to fix a GCC 4.9 aarch64 code gen bug. |
| 243 // See comment at the top of the file. |
| 244 virtual int forceUseForBug() = 0; |
| 232 }; | 245 }; |
| 233 | 246 |
| 234 class HorizontalPositions final : public PositionReaderInterface { | 247 class HorizontalPositions final : public PositionReaderInterface { |
| 235 public: | 248 public: |
| 236 explicit HorizontalPositions(const SkScalar* positions) | 249 explicit HorizontalPositions(const SkScalar* positions) |
| 237 : fPositions(positions) { } | 250 : fPositions(positions) { } |
| 238 | 251 |
| 239 SkPoint nextPoint() override { | 252 SkPoint nextPoint() override { |
| 240 SkScalar x = *fPositions++; | 253 SkScalar x = *fPositions++; |
| 241 return {x, 0}; | 254 return {x, 0}; |
| 242 } | 255 } |
| 243 | 256 |
| 257 int forceUseForBug() override { return 1; } |
| 258 |
| 244 private: | 259 private: |
| 245 const SkScalar* fPositions; | 260 const SkScalar* fPositions; |
| 246 }; | 261 }; |
| 247 | 262 |
| 248 class ArbitraryPositions final : public PositionReaderInterface { | 263 class ArbitraryPositions final : public PositionReaderInterface { |
| 249 public: | 264 public: |
| 250 explicit ArbitraryPositions(const SkScalar* positions) | 265 explicit ArbitraryPositions(const SkScalar* positions) |
| 251 : fPositions(positions) { } | 266 : fPositions(positions) { } |
| 252 | 267 |
| 253 SkPoint nextPoint() override { | 268 SkPoint nextPoint() override { |
| 254 SkPoint to_return{fPositions[0], fPositions[1]}; | 269 SkPoint to_return{fPositions[0], fPositions[1]}; |
| 255 fPositions += 2; | 270 fPositions += 2; |
| 256 return to_return; | 271 return to_return; |
| 257 } | 272 } |
| 258 | 273 |
| 274 int forceUseForBug() override { return 2; } |
| 275 |
| 259 private: | 276 private: |
| 260 const SkScalar* fPositions; | 277 const SkScalar* fPositions; |
| 261 }; | 278 }; |
| 262 | 279 |
| 263 typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, Arb
itraryPositions> | 280 typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, Arb
itraryPositions> |
| 264 PositionReader; | 281 PositionReader; |
| 265 | 282 |
| 266 // MapperInterface given a point map it through the matrix. There are severa
l shortcut | 283 // MapperInterface given a point map it through the matrix. There are severa
l shortcut |
| 267 // variants. | 284 // variants. |
| 268 // * TranslationMapper - assumes a translation only matrix. | 285 // * TranslationMapper - assumes a translation only matrix. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 }; | 420 }; |
| 404 | 421 |
| 405 // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pix
el positioning is | 422 // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pix
el positioning is |
| 406 // requested. After it has found and placed the glyph it calls the templated
function | 423 // requested. After it has found and placed the glyph it calls the templated
function |
| 407 // ProcessOneGlyph in order to actually perform an action. | 424 // ProcessOneGlyph in order to actually perform an action. |
| 408 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, | 425 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, |
| 409 SkAxisAlignment kAxisAlignment> | 426 SkAxisAlignment kAxisAlignment> |
| 410 class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<Pr
ocessOneGlyph> { | 427 class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<Pr
ocessOneGlyph> { |
| 411 public: | 428 public: |
| 412 GlyphFindAndPlaceSubpixel(LookupGlyph& glyphFinder) | 429 GlyphFindAndPlaceSubpixel(LookupGlyph& glyphFinder) |
| 413 : fGlyphFinder(glyphFinder) { } | 430 : fGlyphFinder(glyphFinder) { |
| 431 FixGCC49Arm64Bug(1); |
| 432 } |
| 414 | 433 |
| 415 SkPoint findAndPositionGlyph( | 434 SkPoint findAndPositionGlyph( |
| 416 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly
ph) override { | 435 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly
ph) override { |
| 417 SkPoint finalPosition = position; | 436 SkPoint finalPosition = position; |
| 418 if (kTextAlignment != SkPaint::kLeft_Align) { | 437 if (kTextAlignment != SkPaint::kLeft_Align) { |
| 419 // Get the width of an un-sub-pixel positioned glyph for calcula
ting the | 438 // Get the width of an un-sub-pixel positioned glyph for calcula
ting the |
| 420 // alignment. This is not needed for kLeftAlign because its adju
stment is | 439 // alignment. This is not needed for kLeftAlign because its adju
stment is |
| 421 // always {0, 0}. | 440 // always {0, 0}. |
| 422 const char* tempText = *text; | 441 const char* tempText = *text; |
| 423 const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText
); | 442 const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText
); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 }; | 476 }; |
| 458 | 477 |
| 459 // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub
-pixel | 478 // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub
-pixel |
| 460 // positioning is requested. The kUseKerning argument should be true for dra
wText, and false | 479 // positioning is requested. The kUseKerning argument should be true for dra
wText, and false |
| 461 // for drawPosText. | 480 // for drawPosText. |
| 462 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKern
ing kUseKerning> | 481 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKern
ing kUseKerning> |
| 463 class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<P
rocessOneGlyph> { | 482 class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<P
rocessOneGlyph> { |
| 464 public: | 483 public: |
| 465 GlyphFindAndPlaceFullPixel(LookupGlyph& glyphFinder) | 484 GlyphFindAndPlaceFullPixel(LookupGlyph& glyphFinder) |
| 466 : fGlyphFinder(glyphFinder) { | 485 : fGlyphFinder(glyphFinder) { |
| 486 FixGCC49Arm64Bug(2); |
| 467 // Kerning can only be used with SkPaint::kLeft_Align | 487 // Kerning can only be used with SkPaint::kLeft_Align |
| 468 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment
, | 488 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment
, |
| 469 "Kerning can only be used with left aligned text."); | 489 "Kerning can only be used with left aligned text."); |
| 470 } | 490 } |
| 471 | 491 |
| 472 SkPoint findAndPositionGlyph( | 492 SkPoint findAndPositionGlyph( |
| 473 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly
ph) override { | 493 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly
ph) override { |
| 474 SkPoint finalPosition = position; | 494 SkPoint finalPosition = position; |
| 475 const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text); | 495 const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text); |
| 476 if (kUseKerning) { | 496 if (kUseKerning) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 return; | 614 return; |
| 595 } | 615 } |
| 596 | 616 |
| 597 PositionReader positionReader{ | 617 PositionReader positionReader{ |
| 598 [&](PositionReader::Variants* to_init) { | 618 [&](PositionReader::Variants* to_init) { |
| 599 if (2 == scalarsPerPosition) { | 619 if (2 == scalarsPerPosition) { |
| 600 to_init->initialize<ArbitraryPositions>(pos); | 620 to_init->initialize<ArbitraryPositions>(pos); |
| 601 } else { | 621 } else { |
| 602 to_init->initialize<HorizontalPositions>(pos); | 622 to_init->initialize<HorizontalPositions>(pos); |
| 603 } | 623 } |
| 624 positionReader->forceUseForBug(); |
| 604 } | 625 } |
| 605 }; | 626 }; |
| 606 | 627 |
| 607 Mapper mapper{ | 628 Mapper mapper{ |
| 608 [&](Mapper::Variants* to_init) { | 629 [&](Mapper::Variants* to_init) { |
| 609 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask) | 630 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask) |
| 610 || scalarsPerPosition == 2) { | 631 || scalarsPerPosition == 2) { |
| 611 to_init->initialize<GeneralMapper>(matrix, offset); | 632 to_init->initialize<GeneralMapper>(matrix, offset); |
| 612 } else if (mtype & SkMatrix::kScale_Mask) { | 633 } else if (mtype & SkMatrix::kScale_Mask) { |
| 613 to_init->initialize<XScaleMapper>(matrix, offset); | 634 to_init->initialize<XScaleMapper>(matrix, offset); |
| 614 } else { | 635 } else { |
| 615 to_init->initialize<TranslationMapper>(matrix, offset); | 636 to_init->initialize<TranslationMapper>(matrix, offset); |
| 616 } | 637 } |
| 617 } | 638 } |
| 618 }; | 639 }; |
| 619 | 640 |
| 620 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{ | 641 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition { |
| 621 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) { | 642 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) { |
| 622 if (cache->isSubpixel()) { | 643 if (cache->isSubpixel()) { |
| 623 switch (textAlignment) { | 644 switch (textAlignment) { |
| 624 case SkPaint::kLeft_Align: | 645 case SkPaint::kLeft_Align: |
| 625 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>( | 646 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>( |
| 626 to_init, axisAlignment, glyphFinder); | 647 to_init, axisAlignment, glyphFinder); |
| 627 break; | 648 break; |
| 628 case SkPaint::kCenter_Align: | 649 case SkPaint::kCenter_Align: |
| 629 InitSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align>( | 650 InitSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align>( |
| 630 to_init, axisAlignment, glyphFinder); | 651 to_init, axisAlignment, glyphFinder); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 SkPoint current = offset; | 724 SkPoint current = offset; |
| 704 while (text < stop) { | 725 while (text < stop) { |
| 705 current = | 726 current = |
| 706 findAndPosition->findAndPositionGlyph( | 727 findAndPosition->findAndPositionGlyph( |
| 707 &text, current, skstd::forward<ProcessOneGlyph>(processOneGlyph)
); | 728 &text, current, skstd::forward<ProcessOneGlyph>(processOneGlyph)
); |
| 708 | 729 |
| 709 } | 730 } |
| 710 } | 731 } |
| 711 | 732 |
| 712 #endif // SkFindAndPositionGlyph_DEFINED | 733 #endif // SkFindAndPositionGlyph_DEFINED |
| OLD | NEW |