| // Copyright 2021 Google LLC. |
| #ifndef Painter_DEFINED |
| #define Painter_DEFINED |
| #include "experimental/sktext/include/Text.h" |
| #include "experimental/sktext/include/Types.h" |
| #include "include/core/SkCanvas.h" |
| |
| namespace skia { |
| namespace text { |
| |
| struct DecoratedBlock { |
| DecoratedBlock(uint32_t count, SkPaint fg, SkPaint bg) |
| : charCount(count) |
| , foregroundPaint(std::move(fg)) |
| , backgroundPaint(std::move(bg)) { } |
| uint32_t charCount; |
| SkPaint foregroundPaint; |
| SkPaint backgroundPaint; |
| }; |
| |
| class TrivialFontChain : public FontChain { |
| public: |
| TrivialFontChain(const char* ff, SkScalar size, SkFontStyle fontStyle) |
| : fTypeface(sk_sp<SkTypeface>(SkFontMgr::RefDefault()->matchFamilyStyle(ff, SkFontStyle::Normal()))) |
| , fSize(size) |
| , fFontStyle(fontStyle) { } |
| size_t count() const override { return (size_t)1; } |
| sk_sp<SkTypeface> operator[](size_t index) const override { |
| SkASSERT(index == 0); |
| return fTypeface; |
| } |
| float fontSize() const override { return fSize; } |
| SkString locale() const override { return SkString("en"); } |
| sk_sp<SkTypeface> getTypeface() const { return fTypeface; } |
| bool empty() const { return fTypeface == nullptr; } |
| |
| private: |
| sk_sp<SkTypeface> fTypeface; |
| SkScalar fSize; |
| SkFontStyle fFontStyle; |
| }; |
| |
| class MultipleFontChain : public FontChain { |
| public: |
| MultipleFontChain(std::vector<const char*> ffs, SkScalar size, SkFontStyle fontStyle) |
| : fSize(size) |
| , fFontStyle(fontStyle) { |
| for (auto& ff : ffs) { |
| auto typeface = SkFontMgr::RefDefault()->matchFamilyStyle(ff, SkFontStyle::Normal()); |
| if (typeface != nullptr) { |
| fTypefaces.emplace_back(typeface); |
| } |
| } |
| } |
| size_t count() const override { return fTypefaces.size(); } |
| sk_sp<SkTypeface> operator[](size_t index) const override { |
| SkASSERT(index < fTypefaces.size()); |
| return fTypefaces[index]; |
| } |
| float fontSize() const override { return fSize; } |
| SkString locale() const override { return SkString("en"); } |
| bool empty() const { return fTypefaces.empty(); } |
| |
| private: |
| std::vector<sk_sp<SkTypeface>> fTypefaces; |
| SkScalar fSize; |
| SkFontStyle fFontStyle; |
| }; |
| |
| class Paint : public Visitor { |
| public: |
| void paint(SkCanvas* canvas, SkPoint xy, UnicodeText* unicodeText, WrappedText* wrappedText, SkSpan<DecoratedBlock> decoratedBlocks); |
| // Simplification (using default font manager, default font family and default everything possible) |
| static bool drawText(std::u16string text, SkCanvas* canvas, SkScalar x, SkScalar y); |
| static bool drawText(std::u16string text, SkCanvas* canvas, SkScalar width); |
| static bool drawText(std::u16string text, SkCanvas* canvas, |
| TextDirection textDirection, TextAlign textAlign, |
| SkPaint foreground, SkPaint background, |
| const SkString& fontFamily, SkScalar fontSize, SkFontStyle fontStyle, |
| SkScalar x, SkScalar y); |
| static bool drawText(std::u16string text, SkCanvas* canvas, |
| TextDirection textDirection, TextAlign textAlign, |
| SkPaint foreground, SkPaint background, |
| const SkString& fontFamily, SkScalar fontSize, SkFontStyle fontStyle, |
| SkSize reqSize, SkScalar x, SkScalar y); |
| |
| private: |
| static std::unique_ptr<WrappedText> layout(std::u16string text, |
| TextDirection textDirection, TextAlign textAlign, |
| SkSize reqSize, |
| SkSpan<FontBlock> fontBlocks); |
| |
| void onGlyphRun(const SkFont& font, |
| DirTextRange dirTextRange, |
| SkRect bounds, |
| TextIndex trailingSpaces, |
| size_t glyphCount, |
| const uint16_t glyphs[], |
| const SkPoint positions[], |
| const TextIndex clusters[]) override; |
| |
| // We guarantee that the text range will be inside one of the decorated blocks |
| DecoratedBlock findDecoratedBlock(TextRange textRange); |
| |
| SkCanvas* fCanvas; |
| SkPoint fXY; |
| SkSpan<FontBlock> fFontBlocks; |
| SkSpan<DecoratedBlock> fDecoratedBlocks; |
| }; |
| } // namespace text |
| } // namespace skia |
| #endif // Painter_DEFINED |