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:
Julia Lavrova 2020-08-25 11:42:51 -04:00 committed by Skia Commit-Bot
parent da34798bee
commit 36700ef54d
7 changed files with 82 additions and 25 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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 {