| // Copyright 2019 Google LLC. |
| #ifndef ParagraphImpl_DEFINED |
| #define ParagraphImpl_DEFINED |
| |
| #include "include/core/SkPicture.h" |
| #include "include/private/SkTHash.h" |
| #include "modules/skparagraph/include/Paragraph.h" |
| #include "modules/skparagraph/include/ParagraphStyle.h" |
| #include "modules/skparagraph/include/TextStyle.h" |
| #include "modules/skparagraph/src/Run.h" |
| #include "modules/skparagraph/src/TextLine.h" |
| |
| class SkCanvas; |
| |
| namespace skia { |
| namespace textlayout { |
| |
| template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) { |
| return a.size() == b.size() && a.begin() == b.begin(); |
| } |
| |
| template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) { |
| return a.begin() >= b.begin() && a.end() <= b.end(); |
| } |
| |
| class ParagraphImpl final : public Paragraph { |
| public: |
| ParagraphImpl(const SkString& text, |
| ParagraphStyle style, |
| std::vector<Block> blocks, |
| sk_sp<FontCollection> fonts) |
| : Paragraph(std::move(style), std::move(fonts)) |
| , fText(text) |
| , fTextSpan(fText.c_str(), fText.size()) |
| , fDirtyLayout(true) |
| , fOldWidth(0) |
| , fPicture(nullptr) { |
| fTextStyles.reserve(blocks.size()); |
| for (auto& block : blocks) { |
| fTextStyles.emplace_back( |
| SkSpan<const char>(fTextSpan.begin() + block.fStart, block.fEnd - block.fStart), |
| block.fStyle); |
| } |
| } |
| |
| ParagraphImpl(const std::u16string& utf16text, |
| ParagraphStyle style, |
| std::vector<Block> blocks, |
| sk_sp<FontCollection> fonts); |
| ~ParagraphImpl() override; |
| |
| void layout(SkScalar width) override; |
| void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override; |
| std::vector<TextBox> getRectsForRange(unsigned start, |
| unsigned end, |
| RectHeightStyle rectHeightStyle, |
| RectWidthStyle rectWidthStyle) override; |
| PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override; |
| SkRange<size_t> getWordBoundary(unsigned offset) override; |
| bool didExceedMaxLines() override { |
| return !fParagraphStyle.unlimited_lines() && fLines.size() > fParagraphStyle.getMaxLines(); |
| } |
| |
| size_t lineNumber() override { return fLines.size(); } |
| |
| TextLine& addLine(SkVector offset, SkVector advance, SkSpan<const char> text, |
| SkSpan<const char> textWithSpaces, SkSpan<const Cluster> clusters, |
| size_t start, size_t end, LineMetrics sizes); |
| |
| SkSpan<const char> text() const { return fTextSpan; } |
| SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); } |
| SkSpan<TextBlock> styles() { |
| return SkSpan<TextBlock>(fTextStyles.data(), fTextStyles.size()); |
| } |
| SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); } |
| ParagraphStyle paragraphStyle() const { return fParagraphStyle; } |
| SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); } |
| void formatLines(SkScalar maxWidth); |
| |
| bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); } |
| bool strutForceHeight() const { |
| return paragraphStyle().getStrutStyle().getForceStrutHeight(); |
| } |
| LineMetrics strutMetrics() const { return fStrutMetrics; } |
| |
| void markDirty() override { fDirtyLayout = true; } |
| |
| private: |
| friend class ParagraphBuilder; |
| |
| void resetContext(); |
| void resolveStrut(); |
| void buildClusterTable(); |
| bool shapeTextIntoEndlessLine(); |
| void breakShapedTextIntoLines(SkScalar maxWidth); |
| void paintLinesIntoPicture(); |
| |
| SkSpan<const TextBlock> findAllBlocks(SkSpan<const char> text); |
| |
| // Input |
| SkTArray<TextBlock, true> fTextStyles; |
| SkString fText; |
| SkSpan<const char> fTextSpan; |
| |
| // Internal structures |
| SkTArray<Run> fRuns; |
| SkTArray<Cluster, true> fClusters; |
| SkTArray<TextLine> fLines; |
| LineMetrics fStrutMetrics; |
| |
| bool fDirtyLayout; |
| SkScalar fOldWidth; |
| |
| // Painting |
| sk_sp<SkPicture> fPicture; |
| }; |
| } // namespace textlayout |
| } // namespace skia |
| |
| #endif // ParagraphImpl_DEFINED |