Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Private 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
 

Static Public Member Functions

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

Private Member Functions

void beginLine () override
 
void runInfo (const RunInfo &) override
 
void commitRunInfo () override
 
void commitLine () override
 
Buffer runBuffer (const RunInfo &info) override
 
void commitRunBuffer (const RunInfo &) override
 

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)

Member Function Documentation

◆ beginLine()

void skia::textlayout::OneLineShaper::beginLine ( )
inlineoverrideprivatevirtual

Called when beginning a line.

Implements SkShaper::RunHandler.

Definition at line 86 of file OneLineShaper.h.

86{}

◆ commitLine()

void skia::textlayout::OneLineShaper::commitLine ( )
inlineoverrideprivatevirtual

Called when ending a line.

Implements SkShaper::RunHandler.

Definition at line 89 of file OneLineShaper.h.

89{}

◆ commitRunBuffer()

void skia::textlayout::OneLineShaper::commitRunBuffer ( const RunInfo info)
overrideprivatevirtual

Called after each runBuffer is filled out.

Implements SkShaper::RunHandler.

Definition at line 17 of file OneLineShaper.cpp.

17 {
18
19 fCurrentRun->commit();
20
21 auto oldUnresolvedCount = fUnresolvedBlocks.size();
22/*
23 SkDebugf("Run [%zu:%zu)\n", fCurrentRun->fTextRange.start, fCurrentRun->fTextRange.end);
24 for (size_t i = 0; i < fCurrentRun->size(); ++i) {
25 SkDebugf("[%zu] %hu %u %f\n", i, fCurrentRun->fGlyphs[i], fCurrentRun->fClusterIndexes[i], fCurrentRun->fPositions[i].fX);
26 }
27*/
28 // Find all unresolved blocks
29 sortOutGlyphs([&](GlyphRange block){
30 if (block.width() == 0) {
31 return;
32 }
33 addUnresolvedWithRun(block);
34 });
35
36 // Fill all the gaps between unresolved blocks with resolved ones
37 if (oldUnresolvedCount == fUnresolvedBlocks.size()) {
38 // No unresolved blocks added - we resolved the block with one run entirely
39 addFullyResolved();
40 return;
41 } else if (oldUnresolvedCount == fUnresolvedBlocks.size() - 1) {
42 auto& unresolved = fUnresolvedBlocks.back();
43 if (fCurrentRun->textRange() == unresolved.fText) {
44 // Nothing was resolved; preserve the initial run if it makes sense
45 auto& front = fUnresolvedBlocks.front();
46 if (front.fRun != nullptr) {
47 unresolved.fRun = front.fRun;
48 unresolved.fGlyphs = front.fGlyphs;
49 }
50 return;
51 }
52 }
53
54 fillGaps(oldUnresolvedCount);
55}
SkRange< GlyphIndex > GlyphRange
Definition Run.h:44

◆ commitRunInfo()

void skia::textlayout::OneLineShaper::commitRunInfo ( )
inlineoverrideprivatevirtual

Called after all runInfo calls for a line.

Implements SkShaper::RunHandler.

Definition at line 88 of file OneLineShaper.h.

88{}

◆ 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
glong glong end
SK_SPI SkUnichar NextUTF8WithReplacement(const char **ptr, const char *end)
Definition SkUTF.cpp:154

◆ runBuffer()

Buffer skia::textlayout::OneLineShaper::runBuffer ( const RunInfo info)
inlineoverrideprivatevirtual

Called for each run in a line after commitRunInfo. The buffer will be filled out.

Implements SkShaper::RunHandler.

Definition at line 91 of file OneLineShaper.h.

91 {
92 fCurrentRun = std::make_shared<Run>(fParagraph,
93 info,
94 fCurrentText.start,
95 fHeight,
96 fUseHalfLeading,
97 fBaselineShift,
98 ++fUniqueRunId,
99 fAdvance.fX);
100 return fCurrentRun->newRunBuffer();
101 }
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
float fX
x-axis value

◆ runInfo()

void skia::textlayout::OneLineShaper::runInfo ( const RunInfo info)
inlineoverrideprivatevirtual

Called once for each run in a line. Can compute baselines and offsets.

Implements SkShaper::RunHandler.

Definition at line 87 of file OneLineShaper.h.

87{}

◆ 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()
float SkScalar
Definition extension.cpp:12
if(end==-1)
GAsyncResult * result
SKSHAPER_API std::unique_ptr< SkShaper > ShapeDontWrapOrReorder(sk_sp< SkUnicode > unicode, sk_sp< SkFontMgr > fallback)
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: