blob: d1f5ce19ff3774efa5498c88145850383ac07479 [file] [log] [blame]
// Copyright 2021 Google LLC.
#ifndef LogicalRun_DEFINED
#define LogicalRun_DEFINED
#include "experimental/sktext/include/Types.h"
#include "experimental/sktext/src/Line.h"
#include "include/private/base/SkTArray.h"
#include "modules/skshaper/include/SkShaper.h"
namespace skia {
namespace text {
class LogicalRun {
public:
LogicalRun(const SkShaper::RunHandler::RunInfo& info, TextIndex textStart, SkScalar glyphOffset);
SkShaper::RunHandler::Buffer newRunBuffer() {
return {fGlyphs.data(), fPositions.data(), fOffsets.data(), fClusters.data(), {0.0f, 0.0f} };
}
void commit() {
fFont.getBounds(fGlyphs.data(), fGlyphs.size(), fBounds.data(), nullptr);
fPositions[fGlyphs.size()] = fAdvance;
fClusters[fGlyphs.size()] = this->leftToRight() ? fUtf8Range.end() : fUtf8Range.begin();
}
TextRange getTextRange() const { return fUtf16Range; }
SkScalar calculateWidth(GlyphRange glyphRange) const {
SkASSERT(glyphRange.fStart <= glyphRange.fEnd &&
glyphRange.fEnd < SkToSizeT(fPositions.size()));
return fPositions[glyphRange.fEnd].fX - fPositions[glyphRange.fStart].fX;
}
SkScalar calculateWidth(GlyphIndex start, GlyphIndex end) const {
return calculateWidth(GlyphRange(start, end));
}
SkScalar width() const { return fAdvance.fX; }
SkScalar firstGlyphPosition() const { return fPositions[0].fX; }
bool leftToRight() const { return fBidiLevel % 2 == 0; }
uint8_t bidiLevel() const { return fBidiLevel; }
size_t size() const { return fGlyphs.size(); }
LogicalRunType getRunType() const { return fRunType; }
void setRunType(LogicalRunType runType) { fRunType = runType; }
template <typename Callback>
void forEachCluster(Callback&& callback) {
for(int glyph = 0; glyph < fClusters.size(); ++glyph) {
callback(glyph, fRunStart + fClusters[glyph]);
}
}
template <typename Callback>
void convertUtf16Range(Callback&& callback) {
this->fUtf16Range.fStart = callback(this->fUtf8Range.begin());
this->fUtf16Range.fEnd = callback(this->fUtf8Range.end());
}
// Convert indexes into utf16 and also shift them to be on the entire text scale
template <typename Callback>
void convertClusterIndexes(Callback&& callback) {
for (int glyph = 0; glyph < fClusters.size(); ++glyph) {
fClusters[glyph] = callback(fClusters[glyph]);
}
}
private:
friend class ShapedText;
friend class WrappedText;
SkFont fFont;
TextMetrics fTextMetrics;
LogicalRunType fRunType;
SkVector fAdvance;
SkShaper::RunHandler::Range fUtf8Range;
TextRange fUtf16Range;
TextIndex fRunStart;
SkScalar fRunOffset;
SkSTArray<128, SkGlyphID, true> fGlyphs;
SkSTArray<128, SkPoint, true> fPositions;
SkSTArray<128, SkPoint, true> fOffsets;
SkSTArray<128, uint32_t, true> fClusters;
SkSTArray<128, SkRect, true> fBounds;
uint8_t fBidiLevel;
};
} // namespace text
} // namespace skia
#endif