398ef4487b
This reverts commitb51994990b
. Reason for revert: Fixed the test Original change's description: > Revert "Reland "Small changes for SkText that are not in experimental directory"" > > This reverts commitce32c8a074
. > > Reason for revert: Skottie test is broken > > Original change's description: > > Reland "Small changes for SkText that are not in experimental directory" > > > > This reverts commit481a58dfe0
. > > > > Reason for revert: Fixing the build > > > > Original change's description: > > > Revert "Small changes for SkText that are not in experimental directory" > > > > > > This reverts commit92f1bc0083
. > > > > > > Reason for revert: Blocking Android roll. > > > > > > Original change's description: > > > > Small changes for SkText that are not in experimental directory > > > > > > > > (also made utf 8<->16 conversion static on SkUnicode) > > > > > > > > Change-Id: Ie64d18ad21a35ec10bd0b350fb7887fb78a419d8 > > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448140 > > > > Reviewed-by: Mike Reed <reed@google.com> > > > > Commit-Queue: Julia Lavrova <jlavrova@google.com> > > > > > > Change-Id: Ieb9eb0495dddfc0f9e9e74861b24efc0201fd520 > > > No-Presubmit: true > > > No-Tree-Checks: true > > > No-Try: true > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448656 > > > Auto-Submit: Brian Osman <brianosman@google.com> > > > Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> > > > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> > > > > Change-Id: I1e5859c9dd943c701d4c4e648bdc3e44412eca54 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448676 > > Reviewed-by: Brian Osman <brianosman@google.com> > > Commit-Queue: Julia Lavrova <jlavrova@google.com> > > Change-Id: Ib8e5ec05a5555f34106a0ee61878a8199b82bb82 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448897 > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> > Reviewed-by: Florin Malita <fmalita@google.com> > Commit-Queue: Julia Lavrova <jlavrova@google.com> Change-Id: I3bc103c0e1c495342a6673e80765b5f26862e8dc Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448898 Reviewed-by: Florin Malita <fmalita@google.com> Commit-Queue: Julia Lavrova <jlavrova@google.com>
245 lines
8.7 KiB
C++
245 lines
8.7 KiB
C++
/*
|
|
* 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 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;
|
|
|
|
static SkString convertUtf16ToUtf8(const char16_t * utf16, int utf16Units) {
|
|
|
|
int utf8Units = SkUTF::UTF16ToUTF8(nullptr, 0, (uint16_t*)utf16, utf16Units);
|
|
if (utf8Units < 0) {
|
|
SkDEBUGF("Convert error: Invalid utf16 input");
|
|
return SkString();
|
|
}
|
|
SkAutoTArray<char> utf8(utf8Units);
|
|
SkDEBUGCODE(int dstLen =) SkUTF::UTF16ToUTF8(utf8.data(), utf8Units, (uint16_t*)utf16, utf16Units);
|
|
SkASSERT(dstLen == utf8Units);
|
|
|
|
return SkString(utf8.data(), utf8Units);
|
|
}
|
|
|
|
static SkString convertUtf16ToUtf8(const std::u16string& utf16) {
|
|
return convertUtf16ToUtf8(utf16.c_str(), utf16.size());
|
|
}
|
|
|
|
static std::u16string convertUtf8ToUtf16(const char* utf8, int utf8Units) {
|
|
|
|
int utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Units);
|
|
if (utf16Units < 0) {
|
|
SkDEBUGF("Convert error: Invalid utf8 input");
|
|
return std::u16string();
|
|
}
|
|
|
|
SkAutoTArray<uint16_t> utf16(utf16Units);
|
|
SkDEBUGCODE(int dstLen =) SkUTF::UTF8ToUTF16(utf16.data(), utf16Units, utf8, utf8Units);
|
|
SkASSERT(dstLen == utf16Units);
|
|
|
|
return std::u16string((char16_t *)utf16.data(), utf16Units);
|
|
}
|
|
|
|
static std::u16string convertUtf8ToUtf16(const SkString& utf8) {
|
|
return convertUtf8ToUtf16(utf8.c_str(), utf8.size());
|
|
}
|
|
|
|
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;
|
|
uint16_t buffer[2];
|
|
size_t count = SkUTF::ToUTF16(unichar, buffer);
|
|
callback(unichar, before, after, count);
|
|
}
|
|
}
|
|
|
|
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
|