| /* | |
| * Copyright 2016 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef SkShaper_DEFINED | |
| #define SkShaper_DEFINED | |
| #include "include/core/SkFont.h" | |
| #include "include/core/SkFourByteTag.h" | |
| #include "include/core/SkPoint.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkScalar.h" | |
| #include "include/core/SkSpan.h" | |
| #include "include/core/SkString.h" | |
| #include "include/core/SkTextBlob.h" | |
| #include "include/core/SkTypes.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <limits> | |
| #include <memory> | |
| #include <type_traits> | |
| class SkFontStyle; | |
| #if defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| class SkFontMgr; | |
| #else | |
| #include "include/core/SkFontMgr.h" | |
| #endif | |
| #if !defined(SKSHAPER_IMPLEMENTATION) | |
| #define SKSHAPER_IMPLEMENTATION 0 | |
| #endif | |
| #if !defined(SKSHAPER_API) | |
| #if defined(SKSHAPER_DLL) | |
| #if defined(_MSC_VER) | |
| #if SKSHAPER_IMPLEMENTATION | |
| #define SKSHAPER_API __declspec(dllexport) | |
| #else | |
| #define SKSHAPER_API __declspec(dllimport) | |
| #endif | |
| #else | |
| #define SKSHAPER_API __attribute__((visibility("default"))) | |
| #endif | |
| #else | |
| #define SKSHAPER_API | |
| #endif | |
| #endif | |
| class SKSHAPER_API SkShaper { | |
| public: | |
| #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| static std::unique_ptr<SkShaper> MakePrimitive(); | |
| #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) | |
| static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> fallback); | |
| static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> fallback); | |
| static void PurgeHarfBuzzCache(); | |
| #endif | |
| #if defined(SK_SHAPER_CORETEXT_AVAILABLE) | |
| static std::unique_ptr<SkShaper> MakeCoreText(); | |
| #endif | |
| static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> fallback = nullptr); | |
| static void PurgeCaches(); | |
| #endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| SkShaper(); | |
| virtual ~SkShaper(); | |
| class RunIterator { | |
| public: | |
| virtual ~RunIterator() = default; | |
| /** Set state to that of current run and move iterator to end of that run. */ | |
| virtual void consume() = 0; | |
| /** Offset to one past the last (utf8) element in the current run. */ | |
| virtual size_t endOfCurrentRun() const = 0; | |
| /** Return true if consume should no longer be called. */ | |
| virtual bool atEnd() const = 0; | |
| }; | |
| class FontRunIterator : public RunIterator { | |
| public: | |
| virtual const SkFont& currentFont() const = 0; | |
| }; | |
| class BiDiRunIterator : public RunIterator { | |
| public: | |
| /** The unicode bidi embedding level (even ltr, odd rtl) */ | |
| virtual uint8_t currentLevel() const = 0; | |
| }; | |
| class ScriptRunIterator : public RunIterator { | |
| public: | |
| /** Should be iso15924 codes. */ | |
| virtual SkFourByteTag currentScript() const = 0; | |
| }; | |
| class LanguageRunIterator : public RunIterator { | |
| public: | |
| /** Should be BCP-47, c locale names may also work. */ | |
| virtual const char* currentLanguage() const = 0; | |
| }; | |
| struct Feature { | |
| SkFourByteTag tag; | |
| uint32_t value; | |
| size_t start; // Offset to the start (utf8) element of the run. | |
| size_t end; // Offset to one past the last (utf8) element of the run. | |
| }; | |
| private: | |
| template <typename RunIteratorSubclass> | |
| class TrivialRunIterator : public RunIteratorSubclass { | |
| public: | |
| static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, ""); | |
| TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {} | |
| void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; } | |
| size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; } | |
| bool atEnd() const override { return fAtEnd; } | |
| private: | |
| size_t fEnd; | |
| bool fAtEnd; | |
| }; | |
| public: | |
| static std::unique_ptr<FontRunIterator> | |
| MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, | |
| const SkFont& font, sk_sp<SkFontMgr> fallback); | |
| static std::unique_ptr<SkShaper::FontRunIterator> | |
| MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, | |
| const SkFont& font, sk_sp<SkFontMgr> fallback, | |
| const char* requestName, SkFontStyle requestStyle, | |
| const SkShaper::LanguageRunIterator*); | |
| class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { | |
| public: | |
| TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes) | |
| : TrivialRunIterator(utf8Bytes), fFont(font) {} | |
| const SkFont& currentFont() const override { return fFont; } | |
| private: | |
| SkFont fFont; | |
| }; | |
| #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| static std::unique_ptr<BiDiRunIterator> | |
| MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); | |
| #if defined(SK_SHAPER_UNICODE_AVAILABLE) | |
| static std::unique_ptr<BiDiRunIterator> | |
| MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); | |
| #endif // defined(SK_SHAPER_UNICODE_AVAILABLE) | |
| #endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> { | |
| public: | |
| TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes) | |
| : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {} | |
| uint8_t currentLevel() const override { return fBidiLevel; } | |
| private: | |
| uint8_t fBidiLevel; | |
| }; | |
| #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| static std::unique_ptr<ScriptRunIterator> | |
| MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); | |
| #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) | |
| static std::unique_ptr<ScriptRunIterator> | |
| MakeSkUnicodeHbScriptRunIterator(const char* utf8, size_t utf8Bytes); | |
| static std::unique_ptr<ScriptRunIterator> | |
| MakeSkUnicodeHbScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); | |
| // Still used in some cases | |
| static std::unique_ptr<ScriptRunIterator> | |
| MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes); | |
| #endif // defined(SK_SHAPER_HARFBUZZ_AVAILABLE) | |
| #endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> { | |
| public: | |
| TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes) | |
| : TrivialRunIterator(utf8Bytes), fScript(script) {} | |
| SkFourByteTag currentScript() const override { return fScript; } | |
| private: | |
| SkFourByteTag fScript; | |
| }; | |
| static std::unique_ptr<LanguageRunIterator> | |
| MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes); | |
| class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> { | |
| public: | |
| TrivialLanguageRunIterator(const char* language, size_t utf8Bytes) | |
| : TrivialRunIterator(utf8Bytes), fLanguage(language) {} | |
| const char* currentLanguage() const override { return fLanguage.c_str(); } | |
| private: | |
| SkString fLanguage; | |
| }; | |
| class RunHandler { | |
| public: | |
| virtual ~RunHandler() = default; | |
| struct Range { | |
| constexpr Range() : fBegin(0), fSize(0) {} | |
| constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {} | |
| size_t fBegin; | |
| size_t fSize; | |
| constexpr size_t begin() const { return fBegin; } | |
| constexpr size_t end() const { return begin() + size(); } | |
| constexpr size_t size() const { return fSize; } | |
| }; | |
| struct RunInfo { | |
| const SkFont& fFont; | |
| uint8_t fBidiLevel; | |
| SkFourByteTag fScript; | |
| const char* fLanguage; | |
| SkVector fAdvance; | |
| size_t glyphCount; | |
| Range utf8Range; | |
| }; | |
| // glyphs and positions may be null when RunInfo::glyphCount is 0, since nothing is written | |
| struct Buffer { | |
| SkGlyphID* glyphs; // required | |
| SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i] | |
| // if ( offsets) positions[i+1]-positions[i] are advances | |
| SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i] | |
| uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i] | |
| SkPoint point; // offset to add to all positions | |
| }; | |
| /** Called when beginning a line. */ | |
| virtual void beginLine() = 0; | |
| /** Called once for each run in a line. Can compute baselines and offsets. */ | |
| virtual void runInfo(const RunInfo&) = 0; | |
| /** Called after all runInfo calls for a line. */ | |
| virtual void commitRunInfo() = 0; | |
| /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */ | |
| virtual Buffer runBuffer(const RunInfo&) = 0; | |
| /** Called after each runBuffer is filled out. */ | |
| virtual void commitRunBuffer(const RunInfo&) = 0; | |
| /** Called when ending a line. */ | |
| virtual void commitLine() = 0; | |
| }; | |
| #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| virtual void shape(const char* utf8, size_t utf8Bytes, | |
| const SkFont& srcFont, | |
| bool leftToRight, | |
| SkScalar width, | |
| RunHandler*) const = 0; | |
| virtual void shape(const char* utf8, size_t utf8Bytes, | |
| FontRunIterator&, | |
| BiDiRunIterator&, | |
| ScriptRunIterator&, | |
| LanguageRunIterator&, | |
| SkScalar width, | |
| RunHandler*) const = 0; | |
| #endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS) | |
| virtual void shape(const char* utf8, | |
| size_t utf8Bytes, | |
| FontRunIterator&, | |
| BiDiRunIterator&, | |
| ScriptRunIterator&, | |
| LanguageRunIterator&, | |
| const Feature* features, | |
| size_t featuresSize, | |
| SkScalar width, | |
| RunHandler*) const = 0; | |
| struct Options { | |
| // Width available for horizontal layout, before wrapping kicks in. | |
| float width = std::numeric_limits<float>::max(); | |
| // Extra advance added after each glyph, expressed as a fraction of the font size | |
| // (i.e. em units, thus it scales with the text). It applies on top of font kerning | |
| // and participates in line breaking. | |
| float tracking = 0; | |
| }; | |
| virtual void shape(SkSpan<const char> utf8, | |
| FontRunIterator& font, | |
| BiDiRunIterator& bidi, | |
| ScriptRunIterator& script, | |
| LanguageRunIterator& language, | |
| SkSpan<const Feature> features, | |
| const Options& opts, | |
| RunHandler* handler) const = 0; | |
| private: | |
| SkShaper(const SkShaper&) = delete; | |
| SkShaper& operator=(const SkShaper&) = delete; | |
| }; | |
| /** | |
| * Helper for shaping text directly into a SkTextBlob. | |
| */ | |
| class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler { | |
| public: | |
| SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset) | |
| : fUtf8Text(utf8Text) | |
| , fOffset(offset) {} | |
| sk_sp<SkTextBlob> makeBlob(); | |
| SkPoint endPoint() { return fOffset; } | |
| void beginLine() override; | |
| void runInfo(const RunInfo&) override; | |
| void commitRunInfo() override; | |
| Buffer runBuffer(const RunInfo&) override; | |
| void commitRunBuffer(const RunInfo&) override; | |
| void commitLine() override; | |
| private: | |
| SkTextBlobBuilder fBuilder; | |
| char const * const fUtf8Text; | |
| uint32_t* fClusters; | |
| int fClusterOffset; | |
| int fGlyphCount; | |
| SkScalar fMaxRunAscent; | |
| SkScalar fMaxRunDescent; | |
| SkScalar fMaxRunLeading; | |
| SkPoint fCurrentPosition; | |
| SkPoint fOffset; | |
| }; | |
| namespace SkShapers::Primitive { | |
| SKSHAPER_API std::unique_ptr<SkShaper> PrimitiveText(); | |
| SKSHAPER_API std::unique_ptr<SkShaper::BiDiRunIterator> TrivialBiDiRunIterator | |
| (size_t utf8Bytes, uint8_t bidiLevel); | |
| SKSHAPER_API std::unique_ptr<SkShaper::ScriptRunIterator> TrivialScriptRunIterator | |
| (size_t utf8Bytes, SkFourByteTag scriptTag); | |
| } // namespace SkShapers | |
| #endif // SkShaper_DEFINED |