40 auto val = std::fabs(
a);
43 }
else if (val < 100000) {
52 if (
a.start ==
b.start &&
a.end ==
b.end)
return a;
53 auto begin = std::max(
a.start,
b.start);
54 auto end = std::min(
a.end,
b.end);
59 : fFontCollection(
std::move(fonts))
60 , fParagraphStyle(
std::move(style))
61 , fAlphabeticBaseline(0)
62 , fIdeographicBaseline(0)
65 , fMaxIntrinsicWidth(0)
66 , fMinIntrinsicWidth(0)
68 , fExceededMaxLines(0)
80 , fTextStyles(
std::move(blocks))
81 , fPlaceholders(
std::move(placeholders))
84 , fUnresolvedGlyphs(0)
86 , fStrutMetrics(false)
89 , fUnicode(
std::move(unicode))
90 , fHasLineBreaks(false)
91 , fHasWhitespacesInside(false)
106 std::move(placeholders),
121 return fUnresolvedGlyphs;
125 return fUnresolvedCodepoints;
132 fUnresolvedCodepoints.emplace(unichar);
139 auto floorWidth = rawWidth;
146 fLines.size() == 1 && fLines.front().ellipsis() ==
nullptr) {
151 }
else if (fState >=
kLineBroken && fOldWidth != floorWidth) {
169 this->fClusters.clear();
170 this->fClustersIndexFromCodeUnit.
clear();
176 this->computeEmptyMetrics();
177 this->fLines.clear();
191 this->fOldWidth = floorWidth;
192 this->fOldHeight = this->
fHeight;
206 this->computeEmptyMetrics();
207 this->fLines.clear();
219 this->fOldWidth = floorWidth;
220 this->fOldHeight = this->
fHeight;
249 for (
auto& line : fLines) {
250 line.paint(painter,
x,
y);
262 fMaxWidthWithTrailingSpaces = 0;
269 if (
nullptr == fUnicode) {
285 this->paragraphStyle().getReplaceTabCharacters(),
286 &fCodeUnitProperties)) {
291 fTrailingSpaces = fText.
size();
293 for (
int i = 0; i < fCodeUnitProperties.
size(); ++i) {
294 auto flags = fCodeUnitProperties[i];
296 if (fTrailingSpaces == fText.
size()) {
303 fTrailingSpaces = fText.
size();
306 fHasLineBreaks =
true;
310 if (firstWhitespace < fTrailingSpaces) {
311 fHasWhitespacesInside =
true;
330#define M(shift) (1 << (shift))
331 constexpr uint32_t kSpaceMask =
M(kHT) |
M(kLF) |
M(kVT) |
M(kFF) |
M(kCR);
333 return (c == kSP) || (c <= 31 && (kSpaceMask &
M(c)));
345 , fRunIndex(runIndex)
352 , fHalfLetterSpacing(0.0)
353 , fIsIdeographic(false) {
354 size_t whiteSpacesBreakLen = 0;
355 size_t intraWordBreakLen = 0;
357 const char* ch =
text.begin();
358 if (
text.end() - ch == 1 && *(
const unsigned char*)ch <= 0x7F) {
361 ++whiteSpacesBreakLen;
364 for (
auto i = fTextRange.
start; i < fTextRange.
end; ++i) {
366 ++whiteSpacesBreakLen;
372 fIsIdeographic =
true;
377 fIsWhiteSpaceBreak = whiteSpacesBreakLen == fTextRange.
width();
378 fIsIntraWordBreak = intraWordBreakLen == fTextRange.
width();
386 auto correction = 0.0f;
389 correction = fJustificationShifts[
end - 1].fX -
390 fJustificationShifts[
start].fY;
400 size_t letterSpacingStyles = 0;
401 bool hasWordSpacing =
false;
402 for (
auto&
block : fTextStyles) {
405 ++letterSpacingStyles;
408 hasWordSpacing =
true;
413 if (letterSpacingStyles == 0 && !hasWordSpacing) {
419 if (letterSpacingStyles == 1 && !hasWordSpacing && fTextStyles.size() == 1 &&
420 fTextStyles[0].fRange.width() == fText.
size() && fRuns.size() == 1) {
422 auto&
run = fRuns[0];
423 auto& style = fTextStyles[0].fStyle;
424 run.addSpacesEvenly(style.getLetterSpacing());
427 for (
auto&
cluster : fClusters) {
440 bool soFarWhitespacesOnly =
true;
441 bool wordSpacingPending =
false;
442 Cluster* lastSpaceCluster =
nullptr;
443 for (
auto&
run : fRuns) {
446 if (
run.isPlaceholder()) {
450 run.iterateThroughClusters([
this, &
run, &shift, &soFarWhitespacesOnly, &wordSpacingPending, &lastSpaceCluster](
Cluster*
cluster) {
455 Block* currentStyle = fTextStyles.begin();
458 SkASSERT(currentStyle != fTextStyles.end());
466 if (!soFarWhitespacesOnly) {
468 wordSpacingPending =
true;
470 }
else if (wordSpacingPending) {
472 if (
cluster->fRunIndex != lastSpaceCluster->fRunIndex) {
476 lastSpaceCluster->
run().
extend(lastSpaceCluster, spacing);
478 run.addSpacesAtTheEnd(spacing, lastSpaceCluster);
483 wordSpacingPending =
false;
492 soFarWhitespacesOnly =
false;
503 int cluster_count = 1;
504 for (
auto&
run : fRuns) {
505 cluster_count +=
run.isPlaceholder() ? 1 :
run.size();
509 if (!fRuns.empty()) {
513 fClusters.reserve_exact(fClusters.size() + cluster_count);
516 for (
auto&
run : fRuns) {
517 auto runIndex =
run.index();
518 auto runStart = fClusters.size();
519 if (
run.isPlaceholder()) {
521 for (
auto i =
run.textRange().start; i <
run.textRange().end; ++i) {
522 fClustersIndexFromCodeUnit[i] = fClusters.size();
525 fClusters.emplace_back(
this, runIndex, 0ul, 1ul, this->
text(
run.textRange()),
run.advance().fX,
run.advance().fY);
530 run.iterateThroughClustersInTextOrder([runIndex,
this](
size_t glyphStart,
538 for (
auto i = charStart; i < charEnd; ++i) {
539 fClustersIndexFromCodeUnit[i] = fClusters.size();
542 fClusters.emplace_back(
this, runIndex, glyphStart, glyphEnd,
text,
width,
height);
548 run.setClusterRange(runStart, fClusters.size());
551 fClustersIndexFromCodeUnit[fText.
size()] = fClusters.size();
557 if (fText.
size() == 0) {
561 fUnresolvedCodepoints.clear();
562 fFontSwitches.clear();
575 if (!fHasLineBreaks &&
576 !fHasWhitespacesInside &&
577 fPlaceholders.size() == 1 &&
578 fRuns.size() == 1 && fRuns[0].fAdvance.fX <= maxWidth) {
588 auto&
run = this->fRuns[0];
589 auto advance =
run.advance();
591 auto textExcludingSpaces =
TextRange(0, fTrailingSpaces);
598 if (disableFirstAscent) {
599 metrics.fAscent = metrics.fRawAscent;
601 if (disableLastDescent) {
602 metrics.fDescent = metrics.fRawDescent;
610 auto&
cluster = fClusters[trailingSpaces];
616 }
while (trailingSpaces != 0);
618 advance.fY = metrics.
height();
622 textExcludingSpaces, textRange, textRange,
623 clusterRange, clusterRangeWithGhosts,
run.advance().x(),
654 auto& line = this->
addLine(offset, advance, textExcludingSpaces,
text, textWithNewlines,
clusters, clustersWithGhosts, widthWithSpaces, metrics);
656 line.createEllipsis(maxWidth, this->
getEllipsis(),
true);
675 if (!
SkIsFinite(maxWidth) && !isLeftAligned) {
682 for (
auto& line : fLines) {
683 line.format(effectiveAlign, maxWidth);
689 if (!strutStyle.getStrutEnabled() || strutStyle.getFontSize() < 0) {
693 std::vector<sk_sp<SkTypeface>> typefaces =
fFontCollection->findTypefaces(strutStyle.getFontFamilies(), strutStyle.getFontStyle(), std::nullopt);
694 if (typefaces.empty()) {
695 SkDEBUGF(
"Could not resolve strut font\n");
699 SkFont font(typefaces.front(), strutStyle.getFontSize());
701 font.getMetrics(&metrics);
702 const SkScalar strutLeading = strutStyle.getLeading() < 0 ? 0 : strutStyle.getLeading() * strutStyle.getFontSize();
704 if (strutStyle.getHeightOverride()) {
708 if (strutStyle.getHalfLeading()) {
710 auto flexibleHeight = strutStyle.getHeight() * strutStyle.getFontSize() - occupiedHeight;
713 strutAscent = metrics.
fAscent - flexibleHeight;
714 strutDescent = metrics.
fDescent + flexibleHeight;
717 const auto strutHeightMultiplier = strutMetricsHeight == 0
718 ? strutStyle.getHeight()
719 : strutStyle.getHeight() * strutStyle.getFontSize() / strutMetricsHeight;
720 strutAscent = metrics.
fAscent * strutHeightMultiplier;
721 strutDescent = metrics.
fDescent * strutHeightMultiplier;
740 for (
int index = 0; index < fTextStyles.size(); ++index) {
741 auto&
block = fTextStyles[index];
774 return fLines.emplace_back(
this,
offset, advance,
blocks,
775 textExcludingSpaces,
text, textIncludingNewLines,
776 clusters, clustersWithGhosts, widthWithSpaces, sizes);
785 std::vector<TextBox> results;
814 auto utf8 = fUTF8IndexForUTF16Index[
start];
816 if (
start > 0 && fUTF8IndexForUTF16Index[
start - 1] == utf8) {
817 utf8 = fUTF8IndexForUTF16Index[
start + 1];
826 for (
auto& line : fLines) {
827 auto lineText = line.textWithNewlines();
833 line.getRectsForRange(
intersect, rectHeightStyle, rectWidthStyle, results);
849 std::vector<TextBox> boxes;
853 if (fPlaceholders.size() == 1) {
857 for (
auto& line : fLines) {
858 line.getRectsForPlaceholders(boxes);
883 for (
auto& line : fLines) {
885 auto offsetY = line.offset().fY;
886 if (dy >=
offsetY + line.height() && &line != &fLines.back()) {
894 auto result = line.getGlyphPositionAtCoordinate(dx);
908 if (fWords.empty()) {
916 for (
size_t i = 0; i < fWords.size(); ++i) {
917 auto word = fWords[i];
921 }
else if (word >
offset) {
933 for (
auto& line : fLines) {
934 metrics.emplace_back(line.getMetrics());
968 return fTextStyles[blockIndex];
972 if (fState <=
state) {
1010void ParagraphImpl::computeEmptyMetrics() {
1018 bool emptyParagraph = fRuns.empty();
1020 if (emptyParagraph && !fTextStyles.empty()) {
1021 textStyle = fTextStyles.back().fStyle;
1026 auto typeface = typefaces.empty() ? nullptr : typefaces.front();
1029 fEmptyMetrics = InternalLineMetrics(font,
paragraphStyle().getStrutStyle().getForceStrutHeight());
1033 const auto intrinsicHeight = fEmptyMetrics.
height();
1039 fEmptyMetrics.
leading() + strutHeight - intrinsicHeight);
1041 const auto multiplier = strutHeight / intrinsicHeight;
1043 fEmptyMetrics.
ascent() * multiplier,
1044 fEmptyMetrics.
descent() * multiplier,
1045 fEmptyMetrics.
leading() * multiplier);
1049 if (emptyParagraph) {
1056 disableFirstAscent ? fEmptyMetrics.
rawAscent() : fEmptyMetrics.
ascent(),
1070 if (!ellipsis8.isEmpty()) {
1084 for (
auto& textStyle : fTextStyles) {
1088 fState = std::min(fState,
kIndexed);
1107 for (
auto& textStyle : fTextStyles) {
1118 for (
auto& textStyle : fTextStyles) {
1130 for (
auto index = textRange.
start; index < textRange.
end; ++index) {
1147 while (utf8 < fText.
size() &&
1155 while (utf8 < fText.
size() &&
1171 fillUTF16MappingOnce([&] {
1174 [&](
size_t index) { fUTF8IndexForUTF16Index.
emplace_back(index); },
1175 [&](
size_t index) { fUTF16IndexForUTF8Index.
emplace_back(index); });
1181 for (
auto& line : fLines) {
1182 line.ensureTextBlobCachePopulated();
1183 for (
auto& rec : line.fTextBlobCache) {
1184 if (rec.fBlob ==
nullptr) {
1191 const Run*
R = rec.fVisitor_Run;
1192 const uint32_t* clusterPtr = &
R->fClusterIndexes[0];
1194 if (
R->fClusterStart > 0) {
1197 for (
int i = 0; i <
count; ++i) {
1198 clusterStorage[i] =
R->fClusterStart +
R->fClusterIndexes[i];
1200 clusterPtr = &clusterStorage[0];
1202 clusterPtr += rec.fVisitor_Pos;
1208 rec.fClipRect.fRight,
1216 clusterPtr +=
run.count;
1225 if (codeUnitIndex >= fText.
size()) {
1228 size_t startLine = 0;
1229 size_t endLine = fLines.size() - 1;
1230 if (fLines.empty() || fLines[endLine].textWithNewlines().end <= codeUnitIndex) {
1234 while (endLine > startLine) {
1236 const size_t midLine = (endLine + startLine) / 2;
1237 const TextRange midLineRange = fLines[midLine].textWithNewlines();
1238 if (codeUnitIndex < midLineRange.
start) {
1239 endLine = midLine - 1;
1240 }
else if (midLineRange.
end <= codeUnitIndex) {
1241 startLine = midLine + 1;
1252 if (codeUnitIndex >=
SkToSizeT(fUTF8IndexForUTF16Index.
size())) {
1255 const TextIndex utf8 = fUTF8IndexForUTF16Index[codeUnitIndex];
1260 if (lineNumber < 0 || lineNumber >= fLines.size()) {
1265 *lineMetrics = line.getMetrics();
1271 if (lineNumber < 0 || lineNumber >= fLines.size()) {
1275 return includeSpaces ? line.text() : line.trimmedText();
1284 for (
auto c = line.clustersWithSpaces().start; c < line.clustersWithSpaces().end; ++c) {
1287 std::vector<TextBox> boxes;
1292 if (!boxes.empty()) {
1311 return this->
getGlyphClusterAt(fUTF8IndexForUTF16Index[utf16Offset], glyphInfo);
1316 if (codeUnitIndex >=
SkToSizeT(fUTF8IndexForUTF16Index.
size())) {
1319 const TextIndex utf8 = fUTF8IndexForUTF16Index[codeUnitIndex];
1324 if (glyphInfo ==
nullptr) {
1334 std::vector<TextBox> boxes;
1339 if (glyphInfo && !boxes.empty()) {
1342 { fUTF16IndexForUTF8Index[startIndex], fUTF16IndexForUTF8Index[endIndex] },
1358 for (
auto&
run : fRuns) {
1359 const auto textRange =
run.textRange();
1360 if (textRange.start <= codeUnitIndex && codeUnitIndex < textRange.end) {
1369 if (codeUnitIndex >=
SkToSizeT(fUTF8IndexForUTF16Index.
size())) {
1372 const TextIndex utf8 = fUTF8IndexForUTF16Index[codeUnitIndex];
1373 for (
auto&
run : fRuns) {
1374 const auto textRange =
run.textRange();
1375 if (textRange.start <= utf8 && utf8 < textRange.end) {
1383 std::vector<FontInfo> results;
1384 for (
auto&
run : fRuns) {
1385 results.emplace_back(
run.font(),
run.textRange());
1392 for (
auto& line : fLines) {
1393 line.iterateThroughVisualRuns(
1399 *runWidthInLine = line.iterateThroughSingleRunByStyles(
1412 line.offset().fY + correctedBaseline);
1416 run->font().getBounds(
run->glyphs().data(),
1421 const uint32_t* clusterPtr =
run->clusterIndexes().data();
1422 if (
run->fClusterStart > 0) {
1424 for (
size_t i = 0; i < context.
size; ++i) {
1426 run->fClusterStart +
run->fClusterIndexes[i];
1428 clusterPtr = &clusterStorage[0];
1435 &
run->glyphs()[context.
pos],
1436 &
run->fPositions[context.
pos],
1437 &glyphBounds[context.
pos],
1451 int notConverted = 0;
1453 line.iterateThroughVisualRuns(
1459 *runWidthInLine = line.iterateThroughSingleRunByStyles(
1473 line.offset().fY + correctedBaseline);
1482 &
run->positions()[context.
pos], 0};
1483 font.getPaths(&
run->glyphs()[context.
pos], context.
size,
1485 Rec* rec = reinterpret_cast<Rec*>(ctx);
1487 SkMatrix total = mx;
1488 total.postTranslate(rec->fPos->fX + rec->fOffset.fX,
1489 rec->fPos->fY + rec->fOffset.fY);
1490 rec->fPath->addPath(*path, total);
1492 rec->fNotConverted++;
1496 notConverted += rec.fNotConverted;
1501 return notConverted;
1507 while (!iter.
done()) {
1514 Rec* rec = (Rec*)ctx;
1517 tmp.postTranslate(rec->fPos->fX - rec->fOffset.fX,
1518 rec->fPos->fY - rec->fOffset.fY);
1519 rec->fDst->addPath(*src, tmp);
1534 this->getUnicode()->forEachCodepoint(iter.
text(), iter.
textSize(),
1536 if (this->getUnicode()->isEmoji(unichar)) {
1545bool ParagraphImpl::containsColorFontOrBitmap(
SkTextBlob* textBlob) {
1553 if (path == nullptr) {
1554 bool* flag1 = (bool*)ctx;
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static bool intersect(const SkPoint &p0, const SkPoint &n0, const SkPoint &p1, const SkPoint &n1, SkScalar *t)
static bool SkIsFinite(T x, Pack... values)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define SkScalarFloorToScalar(x)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkScalarRoundToScalar(x)
constexpr size_t SkToSizeT(S x)
constexpr int SkToInt(S x)
constexpr int16_t SkToS16(S x)
constexpr uint32_t SkToU32(S x)
void getPaths(const SkGlyphID glyphIDs[], int count, void(*glyphPathProc)(const SkPath *pathOrNull, const SkMatrix &mx, void *ctx), void *ctx) const
constexpr T * end() const
const char * c_str() const
const SkPoint * points() const
const uint16_t * glyphs() const
uint32_t glyphCount() const
uint32_t textSize() const
const SkFont & font() const
bool experimentalNext(ExperimentalRun *)
const SkRect & bounds() const
virtual bool getWords(const char utf8[], int utf8Units, const char *locale, std::vector< Position > *results)=0
static bool hasPartOfWhiteSpaceBreakFlag(SkUnicode::CodeUnitFlags flags)
static bool hasHardLineBreakFlag(SkUnicode::CodeUnitFlags flags)
void forEachCodepoint(const char *utf8, int32_t utf8Units, Callback &&callback)
static SkString convertUtf16ToUtf8(const char16_t *utf16, int utf16Units)
static bool extractUtfConversionMapping(SkSpan< const char > utf8, Appender8 &&appender8, Appender16 &&appender16)
virtual bool getBidiRegions(const char utf8[], int utf8Units, TextDirection dir, std::vector< BidiRegion > *results)=0
virtual bool computeCodeUnitFlags(char utf8[], int utf8Units, bool replaceTabs, skia_private::TArray< SkUnicode::CodeUnitFlags, true > *results)=0
TextRange textRange() const
bool contains(TextIndex ch) const
bool startsIn(TextRange text) const
void setHalfLetterSpacing(SkScalar halfLetterSpacing)
bool isWhitespaceBreak() const
SkScalar rawAscent() const
void updateLineMetrics(InternalLineMetrics &metrics)
SkScalar alphabeticBaseline() const
SkScalar ideographicBaseline() const
void setForceStrut(bool value)
SkScalar rawDescent() const
void update(SkScalar a, SkScalar d, SkScalar l)
size_t unresolvedGlyphs()
PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override
TextLine & addLine(SkVector offset, SkVector advance, TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces, InternalLineMetrics sizes)
void updateFontSize(size_t from, size_t to, SkScalar fontSize) override
void paint(SkCanvas *canvas, SkScalar x, SkScalar y) override
SkFont getFontAtUTF16Offset(size_t codeUnitIndex) override
InternalLineMetrics strutMetrics() const
int getLineNumberAt(TextIndex codeUnitIndex) const override
bool computeCodeUnitProperties()
void extendedVisit(const ExtendedVisitor &) override
void applySpacingAndBuildClusterTable()
ClusterIndex clusterIndex(TextIndex textIndex)
SkSpan< Cluster > clusters()
~ParagraphImpl() override
bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const
sk_sp< FontCollection > fontCollection() const
bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo *glyphInfo) override
TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const
void visit(const Visitor &) override
Cluster & cluster(ClusterIndex clusterIndex)
std::vector< TextBox > getRectsForPlaceholders() override
SkSpan< const char > text() const
skia_private::TArray< TextIndex > countSurroundingGraphemes(TextRange textRange) const
std::vector< FontInfo > getFonts() const override
bool strutForceHeight() const
bool getApplyRoundingHack() const
bool getClosestUTF16GlyphInfoAt(SkScalar dx, SkScalar dy, GlyphInfo *graphemeInfo) override
SkString getEllipsis() const
const ParagraphStyle & paragraphStyle() const
int getPath(int lineNumber, SkPath *dest) override
bool strutEnabled() const
std::unordered_set< SkUnichar > unresolvedCodepoints() override
void getLineMetrics(std::vector< LineMetrics > &) override
ParagraphImpl(const SkString &text, ParagraphStyle style, skia_private::TArray< Block, true > blocks, skia_private::TArray< Placeholder, true > placeholders, sk_sp< FontCollection > fonts, sk_sp< SkUnicode > unicode)
InternalState state() const
size_t lineNumber() override
bool getLineMetricsAt(int lineNumber, LineMetrics *lineMetrics) const override
SkRange< size_t > getWordBoundary(unsigned offset) override
bool getClosestGlyphClusterAt(SkScalar dx, SkScalar dy, GlyphClusterInfo *glyphInfo) override
Run & runByCluster(ClusterIndex clusterIndex)
TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const
void breakShapedTextIntoLines(SkScalar maxWidth)
int32_t unresolvedGlyphs() override
SkSpan< Block > blocks(BlockRange blockRange)
void updateTextAlign(TextAlign textAlign) override
void layout(SkScalar width) override
void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override
bool getGlyphInfoAtUTF16Offset(size_t codeUnitIndex, GlyphInfo *graphemeInfo) override
Block & block(BlockIndex blockIndex)
void addUnresolvedCodepoints(TextRange textRange)
void setState(InternalState state)
BlockRange findAllBlocks(TextRange textRange)
void ensureUTF16Mapping()
void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override
void formatLines(SkScalar maxWidth)
SkFont getFontAt(TextIndex codeUnitIndex) const override
bool shapeTextIntoEndlessLine()
std::vector< TextBox > getRectsForRange(unsigned start, unsigned end, RectHeightStyle rectHeightStyle, RectWidthStyle rectWidthStyle) override
TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const
TextIndex findNextGraphemeBoundary(TextIndex utf8) const
int getLineNumberAtUTF16Offset(size_t codeUnitIndex) override
TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override
SkScalar fIdeographicBaseline
SkScalar fAlphabeticBaseline
ParagraphStyle fParagraphStyle
Paragraph(ParagraphStyle style, sk_sp< FontCollection > fonts)
SkScalar fMaxIntrinsicWidth
SkScalar fMinIntrinsicWidth
sk_sp< FontCollection > fFontCollection
std::function< void(int lineNumber, const ExtendedVisitorInfo *)> ExtendedVisitor
std::function< void(int lineNumber, const VisitorInfo *)> Visitor
SkScalar calculateWidth(size_t start, size_t end, bool clip) const
void addSpacesAtTheEnd(SkScalar space, Cluster *cluster)
void extend(const Cluster *cluster, SkScalar offset)
SkScalar posX(size_t index) const
bool isPlaceholder() const
bool getHeightOverride() const
const std::vector< SkString > & getFontFamilies() const
SkFontStyle getFontStyle() const
SkScalar getHeight() const
SkScalar getBaselineShift() const
SkScalar getLetterSpacing() const
void setBackgroundColor(SkPaint paint)
void setFontSize(SkScalar size)
void setForegroundColor(SkPaint paint)
SkScalar getWordSpacing() const
const std::optional< FontArguments > & getFontArguments() const
SkScalar getFontSize() const
SkScalar minIntrinsicWidth() const
void breakTextIntoLines(ParagraphImpl *parent, SkScalar maxWidth, const AddLineToParagraph &addLine)
bool exceededMaxLines() const
SkScalar maxIntrinsicWidth() const
T & emplace_back(Args &&... args)
static const char * begin(const StringSlice &s)
FlutterSemanticsFlag flag
FlutterSemanticsFlag flags
static bool is_ascii_7bit_space(int c)
TextRange operator*(const TextRange &a, const TextRange &b)
const SkRange< size_t > EMPTY_TEXT
SkRange< size_t > ClusterRange
const SkRange< size_t > EMPTY_RANGE
SkRange< size_t > TextRange
static bool nearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
SkScalar fLeading
distance to add between lines, typically positive or zero
SkScalar fAscent
distance to reserve above baseline, typically negative
SkScalar fDescent
distance to reserve below baseline, typically positive
static constexpr SkPoint Make(float x, float y)
constexpr float left() const
constexpr SkRect makeOffset(float dx, float dy) const
constexpr float top() const
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
static constexpr SkSize Make(SkScalar w, SkScalar h)
std::u16string getEllipsisUtf16() const
bool unlimited_lines() const
void setTextStyle(const TextStyle &textStyle)
TextHeightBehavior getTextHeightBehavior() const
const StrutStyle & getStrutStyle() const
const TextStyle & getTextStyle() const
TextAlign effective_align() const
SkString getEllipsis() const
void setTextAlign(TextAlign align)
TextDirection getTextDirection() const
size_t getMaxLines() const
SkRange< size_t > intersection(SkRange< size_t > other) const
bool getForceStrutHeight() const
bool getStrutEnabled() const