Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | List of all members
skia::textlayout::OneLineShaper Class Reference

#include <OneLineShaper.h>

Inheritance diagram for skia::textlayout::OneLineShaper:
SkShaper::RunHandler

Public Member Functions

 OneLineShaper (ParagraphImpl *paragraph)
 
bool shape ()
 
size_t unresolvedGlyphs ()
 
- Public Member Functions inherited from SkShaper::RunHandler
virtual ~RunHandler ()=default
 
virtual void beginLine ()=0
 
virtual void runInfo (const RunInfo &)=0
 
virtual void commitRunInfo ()=0
 
virtual Buffer runBuffer (const RunInfo &)=0
 
virtual void commitRunBuffer (const RunInfo &)=0
 
virtual void commitLine ()=0
 

Static Public Member Functions

static SkUnichar getEmojiSequenceStart (SkUnicode *unicode, const char **begin, const char *end)
 

Detailed Description

Definition at line 16 of file OneLineShaper.h.

Constructor & Destructor Documentation

◆ OneLineShaper()

skia::textlayout::OneLineShaper::OneLineShaper ( ParagraphImpl paragraph)
inlineexplicit

Definition at line 18 of file OneLineShaper.h.

19 : fParagraph(paragraph)
20 , fHeight(0.0f)
21 , fUseHalfLeading(false)
22 , fBaselineShift(0.0f)
23 , fAdvance(SkPoint::Make(0.0f, 0.0f))
24 , fUnresolvedGlyphs(0)
25 , fUniqueRunId(paragraph->fRuns.size()){ }
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173

Member Function Documentation

◆ getEmojiSequenceStart()

SkUnichar skia::textlayout::OneLineShaper::getEmojiSequenceStart ( SkUnicode unicode,
const char **  begin,
const char *  end 
)
static

This method is based on definition of https://unicode.org/reports/tr51/#def_emoji_sequence It determines if the string begins with an emoji sequence and, if so, return the first codepoint, moving 'begin' pointer to the next once. Otherwise it does not move the pointer and returns -1.

Definition at line 805 of file OneLineShaper.cpp.

805 {
806 const char* next = *begin;
807 auto codepoint1 = SkUTF::NextUTF8WithReplacement(&next, end);
808
809 if (!unicode->isEmoji(codepoint1)) {
810 // This is not a basic emoji nor it an emoji sequence
811 return -1;
812 }
813
814 if (!unicode->isEmojiComponent(codepoint1)) {
815 // This is an emoji sequence start
816 *begin = next;
817 return codepoint1;
818 }
819
820 // Now we need to look at the next codepoint to see what is going on
821 const char* last = next;
822 auto codepoint2 = SkUTF::NextUTF8WithReplacement(&last, end);
823
824 // emoji_flag_sequence
825 if (unicode->isRegionalIndicator(codepoint2)) {
826 // We expect a second regional indicator here
827 if (unicode->isRegionalIndicator(codepoint2)) {
828 *begin = next;
829 return codepoint1;
830 } else {
831 // That really should not happen assuming correct UTF8 text
832 return -1;
833 }
834 }
835
836 // emoji_keycap_sequence
837 if (codepoint2 == 0xFE0F) {
838 auto codepoint3 = SkUTF::NextUTF8WithReplacement(&last, end);
839 if (codepoint3 == 0x20E3) {
840 *begin = next;
841 return codepoint1;
842 }
843 }
844
845 return -1;
846}
static float next(float f)
static const char * begin(const StringSlice &s)
Definition: editor.cpp:252
SK_SPI SkUnichar NextUTF8WithReplacement(const char **ptr, const char *end)
Definition: SkUTF.cpp:154

◆ shape()

bool skia::textlayout::OneLineShaper::shape ( )

Definition at line 617 of file OneLineShaper.cpp.

617 {
618
619 // The text can be broken into many shaping sequences
620 // (by place holders, possibly, by hard line breaks or tabs, too)
621 auto limitlessWidth = std::numeric_limits<SkScalar>::max();
622
623 auto result = iterateThroughShapingRegions(
624 [this, limitlessWidth]
625 (TextRange textRange, SkSpan<Block> styleSpan, SkScalar& advanceX, TextIndex textStart, uint8_t defaultBidiLevel) {
626
627 // Set up the shaper and shape the next
628 auto shaper = SkShapers::HB::ShapeDontWrapOrReorder(fParagraph->fUnicode,
629 SkFontMgr::RefEmpty()); // no fallback
630 if (shaper == nullptr) {
631 // For instance, loadICU does not work. We have to stop the process
632 return false;
633 }
634
635 iterateThroughFontStyles(textRange, styleSpan,
636 [this, &shaper, defaultBidiLevel, limitlessWidth, &advanceX]
637 (Block block, TArray<SkShaper::Feature> features) {
638 auto blockSpan = SkSpan<Block>(&block, 1);
639
640 // Start from the beginning (hoping that it's a simple case one block - one run)
641 fHeight = block.fStyle.getHeightOverride() ? block.fStyle.getHeight() : 0;
642 fUseHalfLeading = block.fStyle.getHalfLeading();
643 fBaselineShift = block.fStyle.getBaselineShift();
644 fAdvance = SkVector::Make(advanceX, 0);
645 fCurrentText = block.fRange;
646 fUnresolvedBlocks.emplace_back(RunBlock(block.fRange));
647
648 this->matchResolvedFonts(block.fStyle, [&](sk_sp<SkTypeface> typeface) {
649
650 // Create one more font to try
651 SkFont font(std::move(typeface), block.fStyle.getFontSize());
652 font.setEdging(SkFont::Edging::kAntiAlias);
653 font.setHinting(SkFontHinting::kSlight);
654 font.setSubpixel(true);
655
656 // Apply fake bold and/or italic settings to the font if the
657 // typeface's attributes do not match the intended font style.
658 int wantedWeight = block.fStyle.getFontStyle().weight();
659 bool fakeBold =
660 wantedWeight >= SkFontStyle::kSemiBold_Weight &&
661 wantedWeight - font.getTypeface()->fontStyle().weight() >= 200;
662 bool fakeItalic =
663 block.fStyle.getFontStyle().slant() == SkFontStyle::kItalic_Slant &&
664 font.getTypeface()->fontStyle().slant() != SkFontStyle::kItalic_Slant;
665 font.setEmbolden(fakeBold);
666 font.setSkewX(fakeItalic ? -SK_Scalar1 / 4 : 0);
667
668 // Walk through all the currently unresolved blocks
669 // (ignoring those that appear later)
670 auto resolvedCount = fResolvedBlocks.size();
671 auto unresolvedCount = fUnresolvedBlocks.size();
672 while (unresolvedCount-- > 0) {
673 auto unresolvedRange = fUnresolvedBlocks.front().fText;
674 if (unresolvedRange == EMPTY_TEXT) {
675 // Duplicate blocks should be ignored
676 fUnresolvedBlocks.pop_front();
677 continue;
678 }
679 auto unresolvedText = fParagraph->text(unresolvedRange);
680
681 SkShaper::TrivialFontRunIterator fontIter(font, unresolvedText.size());
682 LangIterator langIter(unresolvedText, blockSpan,
683 fParagraph->paragraphStyle().getTextStyle());
684 SkShaper::TrivialBiDiRunIterator bidiIter(defaultBidiLevel, unresolvedText.size());
685 auto scriptIter = SkShapers::HB::ScriptRunIterator(unresolvedText.begin(),
686 unresolvedText.size());
687 fCurrentText = unresolvedRange;
688
689 // Map the block's features to subranges within the unresolved range.
690 TArray<SkShaper::Feature> adjustedFeatures(features.size());
691 for (const SkShaper::Feature& feature : features) {
692 SkRange<size_t> featureRange(feature.start, feature.end);
693 if (unresolvedRange.intersects(featureRange)) {
694 SkRange<size_t> adjustedRange = unresolvedRange.intersection(featureRange);
695 adjustedRange.Shift(-static_cast<std::make_signed_t<size_t>>(unresolvedRange.start));
696 adjustedFeatures.push_back({feature.tag, feature.value, adjustedRange.start, adjustedRange.end});
697 }
698 }
699
700 shaper->shape(unresolvedText.begin(), unresolvedText.size(),
701 fontIter, bidiIter,*scriptIter, langIter,
702 adjustedFeatures.data(), adjustedFeatures.size(),
703 limitlessWidth, this);
704
705 // Take off the queue the block we tried to resolved -
706 // whatever happened, we have now smaller pieces of it to deal with
707 fUnresolvedBlocks.pop_front();
708 }
709
710 if (fUnresolvedBlocks.empty()) {
711 // In some cases it does not mean everything
712 // (when we excluded some hopeless blocks from the list)
713 return Resolved::Everything;
714 } else if (resolvedCount < fResolvedBlocks.size()) {
715 return Resolved::Something;
716 } else {
717 return Resolved::Nothing;
718 }
719 });
720
721 this->finish(block, fHeight, advanceX);
722 });
723
724 return true;
725 });
726
727 return result;
728}
static sk_sp< SkFontMgr > RefEmpty()
Definition: SkFontMgr.cpp:154
float SkScalar
Definition: extension.cpp:12
if(end==-1)
GAsyncResult * result
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SKSHAPER_API std::unique_ptr< SkShaper > ShapeDontWrapOrReorder(sk_sp< SkUnicode > unicode, sk_sp< SkFontMgr > fallback)
size_t TextIndex
Definition: TextStyle.h:336
SkRange< size_t > TextRange
Definition: TextStyle.h:337

◆ unresolvedGlyphs()

size_t skia::textlayout::OneLineShaper::unresolvedGlyphs ( )
inline

Definition at line 29 of file OneLineShaper.h.

29{ return fUnresolvedGlyphs; }

The documentation for this class was generated from the following files: