ICU project: script iterator in SkShaper
Change-Id: Idcc9290a7666cb590532150a44304d704c8ee34c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/319777 Commit-Queue: Julia Lavrova <jlavrova@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
da34798bee
commit
36700ef54d
@ -603,8 +603,8 @@ bool OneLineShaper::shape() {
|
||||
LangIterator langIter(unresolvedText, blockSpan,
|
||||
fParagraph->paragraphStyle().getTextStyle());
|
||||
SkShaper::TrivialBiDiRunIterator bidiIter(defaultBidiLevel, unresolvedText.size());
|
||||
auto scriptIter = SkShaper::MakeHbIcuScriptRunIterator
|
||||
(unresolvedText.begin(), unresolvedText.size());
|
||||
auto scriptIter = SkShaper::MakeSkUnicodeHbScriptRunIterator
|
||||
(fParagraph->getUnicode(), unresolvedText.begin(), unresolvedText.size());
|
||||
fCurrentText = unresolvedRange;
|
||||
shaper->shape(unresolvedText.begin(), unresolvedText.size(),
|
||||
fontIter, bidiIter,*scriptIter, langIter,
|
||||
|
@ -3678,7 +3678,9 @@ DEF_TEST(SkParagraph_Ellipsize, reporter) {
|
||||
|
||||
ParagraphStyle paragraph_style;
|
||||
paragraph_style.setMaxLines(1);
|
||||
paragraph_style.setEllipsis(u"\u2026");
|
||||
std::u16string ellipsis = u"\u2026";
|
||||
paragraph_style.setEllipsis(ellipsis);
|
||||
std::u16string e = paragraph_style.getEllipsisUtf16();
|
||||
paragraph_style.turnHintingOff();
|
||||
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
|
||||
|
||||
|
@ -151,7 +151,9 @@ public:
|
||||
|
||||
static std::unique_ptr<ScriptRunIterator>
|
||||
MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script);
|
||||
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
|
||||
#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_UNICODE_AVAILABLE)
|
||||
static std::unique_ptr<ScriptRunIterator>
|
||||
MakeSkUnicodeHbScriptRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes);
|
||||
static std::unique_ptr<ScriptRunIterator>
|
||||
MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes);
|
||||
#endif
|
||||
|
@ -40,6 +40,9 @@ std::unique_ptr<SkShaper::BiDiRunIterator>
|
||||
SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
|
||||
#ifdef SK_UNICODE_AVAILABLE
|
||||
auto unicode = SkUnicode::Make();
|
||||
if (!unicode) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
|
||||
SkShaper::MakeSkUnicodeBidiRunIterator(unicode.get(),
|
||||
utf8,
|
||||
@ -54,9 +57,13 @@ SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLe
|
||||
|
||||
std::unique_ptr<SkShaper::ScriptRunIterator>
|
||||
SkShaper::MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag scriptTag) {
|
||||
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
|
||||
#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_UNICODE_AVAILABLE)
|
||||
auto unicode = SkUnicode::Make();
|
||||
if (!unicode) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<SkShaper::ScriptRunIterator> script =
|
||||
SkShaper::MakeHbIcuScriptRunIterator(utf8, utf8Bytes);
|
||||
SkShaper::MakeSkUnicodeHbScriptRunIterator(unicode.get(), utf8, utf8Bytes);
|
||||
if (script) {
|
||||
return script;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ using HBBuffer = resource<hb_buffer_t , decltype(hb_buffer_destroy), hb_buffer
|
||||
|
||||
using SkUnicodeBidi = std::unique_ptr<SkBidiIterator>;
|
||||
using SkUnicodeBreak = std::unique_ptr<SkBreakIterator>;
|
||||
using SkUnicodeScript = std::unique_ptr<SkScriptIterator>;
|
||||
|
||||
hb_position_t skhb_position(SkScalar value) {
|
||||
// Treat HarfBuzz hb_position_t as 16.16 fixed-point.
|
||||
@ -378,21 +379,19 @@ private:
|
||||
SkBidiIterator::Level fLevel;
|
||||
};
|
||||
|
||||
class HbIcuScriptRunIterator final : public SkShaper::ScriptRunIterator {
|
||||
class SkUnicodeHbScriptRunIterator final: public SkShaper::ScriptRunIterator {
|
||||
public:
|
||||
HbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes)
|
||||
: fCurrent(utf8), fBegin(utf8), fEnd(fCurrent + utf8Bytes)
|
||||
SkUnicodeHbScriptRunIterator(SkUnicodeScript script, const char* utf8, size_t utf8Bytes)
|
||||
: fScript(std::move(script))
|
||||
, fCurrent(utf8), fBegin(utf8), fEnd(fCurrent + utf8Bytes)
|
||||
, fCurrentScript(HB_SCRIPT_UNKNOWN)
|
||||
{}
|
||||
static hb_script_t hb_script_from_icu(SkUnichar u) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UScriptCode scriptCode = uscript_getScript(u, &status);
|
||||
|
||||
if (U_FAILURE (status)) {
|
||||
hb_script_t hb_script_from_icu(SkUnichar u) {
|
||||
SkScriptIterator::ScriptID scriptId;
|
||||
if (!fScript->getScript(u, &scriptId)) {
|
||||
return HB_SCRIPT_UNKNOWN;
|
||||
}
|
||||
|
||||
return hb_icu_script_to_script(scriptCode);
|
||||
return hb_icu_script_to_script((UScriptCode)scriptId);
|
||||
}
|
||||
void consume() override {
|
||||
SkASSERT(fCurrent < fEnd);
|
||||
@ -428,6 +427,7 @@ public:
|
||||
return SkSetFourByteTag(HB_UNTAG(fCurrentScript));
|
||||
}
|
||||
private:
|
||||
SkUnicodeScript fScript;
|
||||
char const * fCurrent;
|
||||
char const * const fBegin;
|
||||
char const * const fEnd;
|
||||
@ -804,7 +804,9 @@ void ShaperHarfBuzz::shape(const char* utf8, size_t utf8Bytes,
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<ScriptRunIterator> script(MakeHbIcuScriptRunIterator(utf8, utf8Bytes));
|
||||
std::unique_ptr<ScriptRunIterator> script(MakeSkUnicodeHbScriptRunIterator(fUnicode.get(),
|
||||
utf8,
|
||||
utf8Bytes));
|
||||
if (!script) {
|
||||
return;
|
||||
}
|
||||
@ -1400,12 +1402,13 @@ ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
|
||||
std::unique_ptr<SkShaper::BiDiRunIterator>
|
||||
SkShaper::MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
|
||||
auto unicode = SkUnicode::Make();
|
||||
std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
|
||||
SkShaper::MakeSkUnicodeBidiRunIterator(unicode.get(),
|
||||
utf8,
|
||||
utf8Bytes,
|
||||
bidiLevel);
|
||||
return bidi;
|
||||
if (!unicode) {
|
||||
return nullptr;
|
||||
}
|
||||
return SkShaper::MakeSkUnicodeBidiRunIterator(unicode.get(),
|
||||
utf8,
|
||||
utf8Bytes,
|
||||
bidiLevel);
|
||||
}
|
||||
|
||||
std::unique_ptr<SkShaper::BiDiRunIterator>
|
||||
@ -1438,7 +1441,20 @@ SkShaper::MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, siz
|
||||
|
||||
std::unique_ptr<SkShaper::ScriptRunIterator>
|
||||
SkShaper::MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes) {
|
||||
return std::make_unique<HbIcuScriptRunIterator>(utf8, utf8Bytes);
|
||||
auto unicode = SkUnicode::Make();
|
||||
if (!unicode) {
|
||||
return nullptr;
|
||||
}
|
||||
return SkShaper::MakeSkUnicodeHbScriptRunIterator(unicode.get(), utf8, utf8Bytes);
|
||||
}
|
||||
|
||||
std::unique_ptr<SkShaper::ScriptRunIterator>
|
||||
SkShaper::MakeSkUnicodeHbScriptRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes) {
|
||||
auto script = unicode->makeScriptIterator();
|
||||
if (!script) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<SkUnicodeHbScriptRunIterator>(std::move(script), utf8, utf8Bytes);
|
||||
}
|
||||
|
||||
std::unique_ptr<SkShaper> SkShaper::MakeShaperDrivenWrapper(sk_sp<SkFontMgr> fontmgr) {
|
||||
|
@ -68,9 +68,15 @@ public:
|
||||
virtual bool setText(const char utftext8[], int utf8Units) = 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 ScriptID;
|
||||
typedef uint32_t CombiningClass;
|
||||
typedef uint32_t GeneralCategory;
|
||||
enum class TextDirection {
|
||||
@ -116,6 +122,7 @@ class SKUNICODE_API SkUnicode {
|
||||
(const char text[], int count, SkBidiIterator::Direction) = 0;
|
||||
virtual std::unique_ptr<SkBreakIterator> makeBreakIterator
|
||||
(const char locale[], BreakType breakType) = 0;
|
||||
virtual std::unique_ptr<SkScriptIterator> makeScriptIterator() = 0;
|
||||
|
||||
// High level methods (that we actually use somewhere=SkParagraph)
|
||||
virtual bool getBidiRegions
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "src/utils/SkUTF.h"
|
||||
#include <unicode/ubidi.h>
|
||||
#include <unicode/ubrk.h>
|
||||
#include <unicode/uscript.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/utext.h>
|
||||
#include <unicode/utypes.h>
|
||||
@ -179,6 +180,25 @@ class SkBreakIterator_icu : public SkBreakIterator {
|
||||
}
|
||||
};
|
||||
|
||||
class SkScriptIterator_icu : public SkScriptIterator {
|
||||
public:
|
||||
bool getScript(SkUnichar u, ScriptID* script) override {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UScriptCode scriptCode = uscript_getScript(u, &status);
|
||||
if (U_FAILURE (status)) {
|
||||
return false;
|
||||
}
|
||||
if (script) {
|
||||
*script = (ScriptID)scriptCode;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::unique_ptr<SkScriptIterator> makeScriptIterator() {
|
||||
return std::unique_ptr<SkScriptIterator>(new SkScriptIterator_icu());
|
||||
}
|
||||
};
|
||||
|
||||
class SkUnicode_icu : public SkUnicode {
|
||||
|
||||
static UBreakIteratorType convertType(BreakType type) {
|
||||
@ -376,6 +396,9 @@ public:
|
||||
BreakType breakType) override {
|
||||
return SkBreakIterator_icu::makeUtf8BreakIterator(locale, breakType);
|
||||
}
|
||||
std::unique_ptr<SkScriptIterator> makeScriptIterator() override {
|
||||
return SkScriptIterator_icu::makeScriptIterator();
|
||||
}
|
||||
|
||||
// TODO: Use ICU data file to detect controls and whitespaces
|
||||
bool isControl(SkUnichar utf8) override {
|
||||
|
Loading…
Reference in New Issue
Block a user