1 // Copyright 2021 Google LLC. 2 #ifndef LogicalRun_DEFINED 3 #define LogicalRun_DEFINED 4 5 #include "experimental/sktext/include/Types.h" 6 #include "experimental/sktext/src/Line.h" 7 #include "modules/skshaper/include/SkShaper.h" 8 9 namespace skia { 10 namespace text { 11 12 class LogicalRun { 13 public: 14 LogicalRun(const SkShaper::RunHandler::RunInfo& info, TextIndex textStart, SkScalar glyphOffset); newRunBuffer()15 SkShaper::RunHandler::Buffer newRunBuffer() { 16 return {fGlyphs.data(), fPositions.data(), fOffsets.data(), fClusters.data(), {0.0f, 0.0f} }; 17 } commit()18 void commit() { 19 fFont.getBounds(fGlyphs.data(), fGlyphs.size(), fBounds.data(), nullptr); 20 fPositions[fGlyphs.size()] = fAdvance; 21 fClusters[fGlyphs.size()] = this->leftToRight() ? fUtf8Range.end() : fUtf8Range.begin(); 22 } 23 getTextRange()24 TextRange getTextRange() const { return fUtf16Range; } 25 calculateWidth(GlyphRange glyphRange)26 SkScalar calculateWidth(GlyphRange glyphRange) const { 27 SkASSERT(glyphRange.fStart <= glyphRange.fEnd && glyphRange.fEnd < fPositions.size()); 28 return fPositions[glyphRange.fEnd].fX - fPositions[glyphRange.fStart].fX; 29 } calculateWidth(GlyphIndex start,GlyphIndex end)30 SkScalar calculateWidth(GlyphIndex start, GlyphIndex end) const { 31 return calculateWidth(GlyphRange(start, end)); 32 } width()33 SkScalar width() const { return fAdvance.fX; } firstGlyphPosition()34 SkScalar firstGlyphPosition() const { return fPositions[0].fX; } 35 leftToRight()36 bool leftToRight() const { return fBidiLevel % 2 == 0; } bidiLevel()37 uint8_t bidiLevel() const { return fBidiLevel; } size()38 size_t size() const { return fGlyphs.size(); } 39 getRunType()40 LogicalRunType getRunType() const { return fRunType; } setRunType(LogicalRunType runType)41 void setRunType(LogicalRunType runType) { fRunType = runType; } 42 43 template <typename Callback> forEachCluster(Callback && callback)44 void forEachCluster(Callback&& callback) { 45 GlyphIndex glyph = 0; 46 for(; glyph < fClusters.size(); ++glyph) { 47 callback(glyph, fRunStart + fClusters[glyph]); 48 } 49 } 50 51 template <typename Callback> convertUtf16Range(Callback && callback)52 void convertUtf16Range(Callback&& callback) { 53 this->fUtf16Range.fStart = callback(this->fUtf8Range.begin()); 54 this->fUtf16Range.fEnd = callback(this->fUtf8Range.end()); 55 } 56 57 // Convert indexes into utf16 and also shift them to be on the entire text scale 58 template <typename Callback> convertClusterIndexes(Callback && callback)59 void convertClusterIndexes(Callback&& callback) { 60 for (size_t glyph = 0; glyph < fClusters.size(); ++glyph) { 61 fClusters[glyph] = callback(fClusters[glyph]); 62 } 63 } 64 65 private: 66 friend class ShapedText; 67 friend class WrappedText; 68 SkFont fFont; 69 TextMetrics fTextMetrics; 70 71 LogicalRunType fRunType; 72 SkVector fAdvance; 73 SkShaper::RunHandler::Range fUtf8Range; 74 TextRange fUtf16Range; 75 TextIndex fRunStart; 76 SkScalar fRunOffset; 77 SkSTArray<128, SkGlyphID, true> fGlyphs; 78 SkSTArray<128, SkPoint, true> fPositions; 79 SkSTArray<128, SkPoint, true> fOffsets; 80 SkSTArray<128, uint32_t, true> fClusters; 81 SkSTArray<128, SkRect, true> fBounds; 82 83 uint8_t fBidiLevel; 84 }; 85 86 } // namespace text 87 } // namespace skia 88 #endif 89