LTR/RTL iterateThroughClustersInGlyphsOrder simplified
Change-Id: I778039babc51b60f745a0acff91008d285d94b93 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/284926 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
parent
5763b37ffb
commit
f4cf893fee
@ -73,6 +73,16 @@ struct TextBox {
|
||||
TextBox(SkRect r, TextDirection d) : rect(r), direction(d) {}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// --- Reversed iterable
|
||||
|
||||
template<typename C, typename UnaryFunction>
|
||||
UnaryFunction directional_for_each(C& c, bool forwards, UnaryFunction f) {
|
||||
return forwards
|
||||
? std::for_each(std::begin(c), std::end(c), f)
|
||||
: std::for_each(std::rbegin(c), std::rend(c), f);
|
||||
}
|
||||
|
||||
const size_t EMPTY_INDEX = std::numeric_limits<size_t>::max();
|
||||
template <typename T> struct SkRange {
|
||||
SkRange() : start(), end() {}
|
||||
@ -99,6 +109,10 @@ template <typename T> struct SkRange {
|
||||
return std::max(start, other.start) <= std::min(end, other.end);
|
||||
}
|
||||
|
||||
SkRange<size_t> intersection(SkRange<size_t> other) const {
|
||||
return SkRange<size_t>(std::max(start, other.start), std::min(end, other.end));
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return start == EMPTY_INDEX && end == EMPTY_INDEX;
|
||||
}
|
||||
|
@ -35,28 +35,13 @@ typedef SkRange<CodepointIndex> CodepointRange;
|
||||
typedef size_t GlyphIndex;
|
||||
typedef SkRange<GlyphIndex> GlyphRange;
|
||||
|
||||
/* This is a part of future LTR/RTL refactoring
|
||||
// This is a part of a shaped text
|
||||
// Text range (a, b) can be:
|
||||
// LTR: [a:b) where a < b
|
||||
// RTL: (b:a] where a > b
|
||||
class ShapedSpan {
|
||||
public:
|
||||
ShapedSpan(Run* run, TextRange textRange, GlyphRange glyphRange)
|
||||
: fRun(run)
|
||||
, fText(textRange)
|
||||
, fGlyphs(glyphRange) { }
|
||||
|
||||
private:
|
||||
Run* fRun;
|
||||
TextRange fText;
|
||||
GlyphRange fGlyphs;
|
||||
};
|
||||
*/
|
||||
struct RunShifts {
|
||||
RunShifts() { }
|
||||
RunShifts(size_t count) { fShifts.push_back_n(count, 0.0); }
|
||||
SkSTArray<128, SkScalar, true> fShifts;
|
||||
// LTR: [start: end) where start <= end
|
||||
// RTL: [end: start) where start >= end
|
||||
class DirText {
|
||||
DirText(bool dir, size_t s, size_t e) : start(s), end(e) { }
|
||||
bool isLeftToRight() const { return start <= end; }
|
||||
size_t start;
|
||||
size_t end;
|
||||
};
|
||||
|
||||
class InternalLineMetrics;
|
||||
|
@ -531,7 +531,7 @@ void TextLine::justify(SkScalar maxWidth) {
|
||||
SkScalar textLen = 0;
|
||||
bool whitespacePatch = false;
|
||||
this->iterateThroughClustersInGlyphsOrder(false, false,
|
||||
[&whitespacePatches, &textLen, &whitespacePatch](const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost) {
|
||||
[&whitespacePatches, &textLen, &whitespacePatch](const Cluster* cluster, bool ghost) {
|
||||
if (cluster->isWhitespaces()) {
|
||||
if (!whitespacePatch) {
|
||||
whitespacePatch = true;
|
||||
@ -555,10 +555,10 @@ void TextLine::justify(SkScalar maxWidth) {
|
||||
auto ghostShift = maxWidth - this->fAdvance.fX;
|
||||
// Spread the extra whitespaces
|
||||
whitespacePatch = false;
|
||||
this->iterateThroughClustersInGlyphsOrder(false, true, [&](const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost) {
|
||||
this->iterateThroughClustersInGlyphsOrder(false, true, [&](const Cluster* cluster, bool ghost) {
|
||||
|
||||
if (ghost) {
|
||||
if (leftToRight) {
|
||||
if (cluster->run()->leftToRight()) {
|
||||
shiftCluster(cluster, ghostShift, ghostShift);
|
||||
}
|
||||
return true;
|
||||
@ -632,7 +632,7 @@ void TextLine::createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool)
|
||||
};
|
||||
|
||||
iterateThroughClustersInGlyphsOrder(
|
||||
true, false, [&](const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost) {
|
||||
true, false, [&](const Cluster* cluster, bool ghost) {
|
||||
return !attachEllipsis(cluster);
|
||||
});
|
||||
|
||||
@ -779,39 +779,29 @@ TextLine::ClipContext TextLine::measureTextInsideOneRun(TextRange textRange,
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextLine::iterateThroughClustersInGlyphsOrder(bool reverse,
|
||||
void TextLine::iterateThroughClustersInGlyphsOrder(bool reversed,
|
||||
bool includeGhosts,
|
||||
const ClustersVisitor& visitor) const {
|
||||
// Walk through the clusters in the logical order (or reverse)
|
||||
for (size_t r = 0; r != fRunsInVisualOrder.size(); ++r) {
|
||||
auto& runIndex = fRunsInVisualOrder[reverse ? fRunsInVisualOrder.size() - r - 1 : r];
|
||||
auto run = this->fMaster->runs().begin() + runIndex;
|
||||
auto start = std::max(run->clusterRange().start, fClusterRange.start);
|
||||
auto end = std::min(run->clusterRange().end, fClusterRange.end);
|
||||
auto ghosts = std::min(run->clusterRange().end, fGhostClusterRange.end);
|
||||
SkSpan<const size_t> runs(fRunsInVisualOrder.data(), fRunsInVisualOrder.size());
|
||||
directional_for_each(runs, reversed, [&](decltype(runs[0]) r) {
|
||||
auto run = this->fMaster->run(r);
|
||||
auto trimmedRange = fClusterRange.intersection(run.clusterRange());
|
||||
auto trailedRange = fGhostClusterRange.intersection(run.clusterRange());
|
||||
SkASSERT(trimmedRange.start == trailedRange.start);
|
||||
|
||||
if (run->leftToRight() != reverse) {
|
||||
for (auto index = start; index < ghosts; ++index) {
|
||||
if (index >= end && !includeGhosts) {
|
||||
break;
|
||||
}
|
||||
const auto& cluster = &fMaster->cluster(index);
|
||||
if (!visitor(cluster, index, run->leftToRight(), index >= end)) {
|
||||
return;
|
||||
}
|
||||
auto trailed = fMaster->clusters(trailedRange);
|
||||
auto trimmed = fMaster->clusters(trimmedRange);
|
||||
directional_for_each(trailed, reversed != run.leftToRight(), [&](Cluster& cluster) {
|
||||
bool ghost = &cluster >= trimmed.end();
|
||||
if (!includeGhosts && ghost) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
for (auto index = ghosts; index > start; --index) {
|
||||
if (index > end && !includeGhosts) {
|
||||
continue;
|
||||
}
|
||||
const auto& cluster = &fMaster->cluster(index - 1);
|
||||
if (!visitor(cluster, index - 1, run->leftToRight(), index > end)) {
|
||||
return;
|
||||
}
|
||||
if (!visitor(&cluster, ghost)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
SkScalar TextLine::iterateThroughSingleRunByStyles(const Run* run,
|
||||
|
@ -68,8 +68,7 @@ public:
|
||||
SkScalar iterateThroughSingleRunByStyles(const Run* run, SkScalar runOffset, TextRange textRange,
|
||||
StyleType styleType, const RunStyleVisitor& visitor) const;
|
||||
|
||||
|
||||
using ClustersVisitor = std::function<bool(const Cluster* cluster, ClusterIndex index, bool leftToRight, bool ghost)>;
|
||||
using ClustersVisitor = std::function<bool(const Cluster* cluster, bool ghost)>;
|
||||
void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const;
|
||||
|
||||
void format(TextAlign effectiveAlign, SkScalar maxWidth);
|
||||
|
Loading…
Reference in New Issue
Block a user