| /* |
| * Copyright 2020 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #ifndef SkUnicode_DEFINED |
| #define SkUnicode_DEFINED |
| |
| #include "include/core/SkSpan.h" |
| #include "include/core/SkTypes.h" |
| #include "src/utils/SkUTF.h" |
| #include <vector> |
| |
| #if !defined(SKUNICODE_IMPLEMENTATION) |
| #define SKUNICODE_IMPLEMENTATION 0 |
| #endif |
| |
| #if !defined(SKUNICODE_API) |
| #if defined(SKUNICODE_DLL) |
| #if defined(_MSC_VER) |
| #if SKUNICODE_IMPLEMENTATION |
| #define SKUNICODE_API __declspec(dllexport) |
| #else |
| #define SKUNICODE_API __declspec(dllimport) |
| #endif |
| #else |
| #define SKUNICODE_API __attribute__((visibility("default"))) |
| #endif |
| #else |
| #define SKUNICODE_API |
| #endif |
| #endif |
| |
| class SKUNICODE_API SkBidiIterator { |
| public: |
| typedef int32_t Position; |
| typedef uint8_t Level; |
| struct Region { |
| Region(Position start, Position end, Level level) |
| : start(start), end(end), level(level) { } |
| Position start; |
| Position end; |
| Level level; |
| }; |
| enum Direction { |
| kLTR, |
| kRTL, |
| }; |
| virtual ~SkBidiIterator() = default; |
| virtual Position getLength() = 0; |
| virtual Level getLevelAt(Position) = 0; |
| static void ReorderVisual(const Level runLevels[], int levelsCount, int32_t logicalFromVisual[]); |
| }; |
| |
| class SKUNICODE_API SkBreakIterator { |
| public: |
| typedef int32_t Position; |
| typedef int32_t Status; |
| virtual ~SkBreakIterator() = default; |
| virtual Position first() = 0; |
| virtual Position current() = 0; |
| virtual Position next() = 0; |
| virtual Position preceding(Position offset) = 0; |
| virtual Position following(Position offset) = 0; |
| virtual Status status() = 0; |
| virtual bool isDone() = 0; |
| virtual bool setText(const char utftext8[], int utf8Units) = 0; |
| virtual bool setText(const char16_t utftext16[], int utf16Units) = 0; |
| }; |
| |
| class SKUNICODE_API SkScriptIterator { |
| public: |
| typedef uint32_t ScriptID; |
| virtual ~SkScriptIterator() = default; |
| virtual bool getScript(SkUnichar u, ScriptID* script) = 0; |
| }; |
| |
| class SKUNICODE_API SkUnicode { |
| public: |
| typedef uint32_t CombiningClass; |
| typedef uint32_t GeneralCategory; |
| enum class TextDirection { |
| kLTR, |
| kRTL, |
| }; |
| typedef size_t Position; |
| typedef uint8_t BidiLevel; |
| struct BidiRegion { |
| BidiRegion(Position start, Position end, BidiLevel level) |
| : start(start), end(end), level(level) { } |
| Position start; |
| Position end; |
| BidiLevel level; |
| }; |
| enum class LineBreakType { |
| kSoftLineBreak = 0, |
| kHardLineBreak = 100, |
| }; |
| |
| enum class BreakType { |
| kWords, |
| kGraphemes, |
| kLines |
| }; |
| struct LineBreakBefore { |
| LineBreakBefore(Position pos, LineBreakType breakType) |
| : pos(pos), breakType(breakType) { } |
| Position pos; |
| LineBreakType breakType; |
| }; |
| |
| virtual ~SkUnicode() = default; |
| |
| virtual bool isControl(SkUnichar utf8) = 0; |
| virtual bool isWhitespace(SkUnichar utf8) = 0; |
| virtual bool isSpace(SkUnichar utf8) = 0; |
| virtual SkString convertUtf16ToUtf8(const std::u16string& utf16) = 0; |
| virtual SkString toUpper(const SkString&) = 0; |
| |
| // Methods used in SkShaper and SkText |
| virtual std::unique_ptr<SkBidiIterator> makeBidiIterator |
| (const uint16_t text[], int count, SkBidiIterator::Direction) = 0; |
| virtual std::unique_ptr<SkBidiIterator> makeBidiIterator |
| (const char text[], int count, SkBidiIterator::Direction) = 0; |
| virtual std::unique_ptr<SkBreakIterator> makeBreakIterator |
| (const char locale[], BreakType breakType) = 0; |
| virtual std::unique_ptr<SkBreakIterator> makeBreakIterator(BreakType type) = 0; |
| virtual std::unique_ptr<SkScriptIterator> makeScriptIterator() = 0; |
| |
| // High level methods (that we actually use somewhere=SkParagraph) |
| virtual bool getBidiRegions |
| (const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* results) = 0; |
| virtual bool getLineBreaks |
| (const char utf8[], int utf8Units, std::vector<LineBreakBefore>* results) = 0; |
| virtual bool getWords |
| (const char utf8[], int utf8Units, std::vector<Position>* results) = 0; |
| virtual bool getGraphemes |
| (const char utf8[], int utf8Units, std::vector<Position>* results) = 0; |
| |
| template <typename Callback> |
| void forEachCodepoint(const char* utf8, int32_t utf8Units, Callback&& callback) { |
| const char* current = utf8; |
| const char* end = utf8 + utf8Units; |
| while (current < end) { |
| auto before = current - utf8; |
| SkUnichar unichar = SkUTF::NextUTF8(¤t, end); |
| if (unichar < 0) unichar = 0xFFFD; |
| auto after = current - utf8; |
| callback(unichar, before, after); |
| } |
| } |
| |
| template <typename Callback> |
| void forEachCodepoint(const char16_t* utf16, int32_t utf16Units, Callback&& callback) { |
| const char16_t* current = utf16; |
| const char16_t* end = utf16 + utf16Units; |
| while (current < end) { |
| auto before = current - utf16; |
| SkUnichar unichar = SkUTF::NextUTF16((const uint16_t**)¤t, (const uint16_t*)end); |
| auto after = current - utf16; |
| callback(unichar, before, after); |
| } |
| } |
| |
| template <typename Callback> |
| void forEachBidiRegion(const uint16_t utf16[], int utf16Units, SkBidiIterator::Direction dir, Callback&& callback) { |
| auto iter = makeBidiIterator(utf16, utf16Units, dir); |
| const uint16_t* start16 = utf16; |
| const uint16_t* end16 = utf16 + utf16Units; |
| SkBidiIterator::Level currentLevel = 0; |
| |
| SkBidiIterator::Position pos16 = 0; |
| while (pos16 <= iter->getLength()) { |
| auto level = iter->getLevelAt(pos16); |
| if (pos16 == 0) { |
| currentLevel = level; |
| } else if (level != currentLevel) { |
| callback(pos16, start16 - utf16, currentLevel); |
| currentLevel = level; |
| } |
| if (start16 == end16) { |
| break; |
| } |
| SkUnichar u = SkUTF::NextUTF16(&start16, end16); |
| pos16 += SkUTF::ToUTF16(u); |
| } |
| } |
| |
| template <typename Callback> |
| void forEachBreak(const char16_t utf16[], int utf16Units, SkUnicode::BreakType type, Callback&& callback) { |
| auto iter = makeBreakIterator(type); |
| iter->setText(utf16, utf16Units); |
| auto pos = iter->first(); |
| do { |
| callback(pos, iter->status()); |
| pos = iter->next(); |
| } while (!iter->isDone()); |
| } |
| |
| virtual void reorderVisual(const BidiLevel runLevels[], int levelsCount, int32_t logicalFromVisual[]) = 0; |
| |
| static std::unique_ptr<SkUnicode> Make(); |
| }; |
| |
| #endif // SkUnicode_DEFINED |