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 |