Reland "Removing ICU dependencies from skparagraph BUILD.gn file"

This reverts commit 05ce2817f2.

Reason for revert: Fixing the build

Original change's description:
> Revert "Removing ICU dependencies from skparagraph BUILD.gn file"
>
> This reverts commit f1711adb1a.
>
> Reason for revert: Build break
>
> Original change's description:
> > Removing ICU dependencies from skparagraph BUILD.gn file
> >
> > (and from the sources, too)
> >
> > Change-Id: I9d8ff51c91aad4b770b1f183c04734d31252b851
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313148
> > Commit-Queue: Julia Lavrova <jlavrova@google.com>
> > Reviewed-by: Ben Wagner <bungeman@google.com>
>
> TBR=bungeman@google.com,jlavrova@google.com
>
> Change-Id: I1fce2436855e3e2a4cb7d1d7204b3ae49fd530e8
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314540
> Reviewed-by: Julia Lavrova <jlavrova@google.com>
> Commit-Queue: Julia Lavrova <jlavrova@google.com>

TBR=bungeman@google.com,jlavrova@google.com

Change-Id: I13d78d75698df47930adc2514d1328abc556a209
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/316444
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
This commit is contained in:
Julia Lavrova 2020-09-11 13:59:49 +00:00 committed by Skia Commit-Bot
parent dd12d9d498
commit b6b7fffc35
24 changed files with 273 additions and 191 deletions

View File

@ -183,21 +183,21 @@ EMSCRIPTEN_BINDINGS(Paragraph) {
.function("layout", &para::ParagraphImpl::layout); .function("layout", &para::ParagraphImpl::layout);
class_<para::ParagraphBuilderImpl>("ParagraphBuilder") class_<para::ParagraphBuilderImpl>("ParagraphBuilder")
.class_function("_Make", optional_override([](SimpleParagraphStyle style, .class_function("_Make", optional_override([](SimpleParagraphStyle style, sk_sp<SkFontMgr> fontMgr)
sk_sp<SkFontMgr> fontMgr)-> para::ParagraphBuilderImpl { -> std::unique_ptr<para::ParagraphBuilderImpl> {
auto fc = sk_make_sp<para::FontCollection>(); auto fc = sk_make_sp<para::FontCollection>();
fc->setDefaultFontManager(fontMgr); fc->setDefaultFontManager(fontMgr);
auto ps = toParagraphStyle(style); auto ps = toParagraphStyle(style);
para::ParagraphBuilderImpl pbi(ps, fc); auto pb = para::ParagraphBuilderImpl::make(ps, fc);
return pbi; return std::unique_ptr<para::ParagraphBuilderImpl>(static_cast<para::ParagraphBuilderImpl*>(pb.release()));
}), allow_raw_pointers()) }), allow_raw_pointers())
.class_function("_MakeFromFontProvider", optional_override([](SimpleParagraphStyle style, .class_function("_MakeFromFontProvider", optional_override([](SimpleParagraphStyle style,
sk_sp<para::TypefaceFontProvider> fontProvider)-> para::ParagraphBuilderImpl { sk_sp<para::TypefaceFontProvider> fontProvider)-> std::unique_ptr<para::ParagraphBuilderImpl> {
auto fc = sk_make_sp<para::FontCollection>(); auto fc = sk_make_sp<para::FontCollection>();
fc->setDefaultFontManager(fontProvider); fc->setDefaultFontManager(fontProvider);
auto ps = toParagraphStyle(style); auto ps = toParagraphStyle(style);
para::ParagraphBuilderImpl pbi(ps, fc); auto pb = para::ParagraphBuilderImpl::make(ps, fc);
return pbi; return std::unique_ptr<para::ParagraphBuilderImpl>(static_cast<para::ParagraphBuilderImpl*>(pb.release()));
}), allow_raw_pointers()) }), allow_raw_pointers())
.function("addText", optional_override([](para::ParagraphBuilderImpl& self, std::string text) { .function("addText", optional_override([](para::ParagraphBuilderImpl& self, std::string text) {
return self.addText(text.c_str(), text.length()); return self.addText(text.c_str(), text.length());

View File

@ -1,6 +1,7 @@
# Copyright 2019 Google LLC. # Copyright 2019 Google LLC.
import("../../gn/skia.gni") import("../../gn/skia.gni")
import("../skshaper/skshaper.gni")
declare_args() { declare_args() {
skia_enable_skparagraph = true skia_enable_skparagraph = true
@ -9,7 +10,8 @@ declare_args() {
paragraph_bench_enabled = false paragraph_bench_enabled = false
} }
if (skia_enable_skparagraph) { if (skia_enable_skparagraph && skia_enable_skshaper && skia_use_icu &&
skia_use_harfbuzz) {
config("public_config") { config("public_config") {
include_dirs = [ include_dirs = [
"include", "include",
@ -21,16 +23,10 @@ if (skia_enable_skparagraph) {
import("skparagraph.gni") import("skparagraph.gni")
public_configs = [ ":public_config" ] public_configs = [ ":public_config" ]
public = skparagraph_public public = skparagraph_public
if (skia_use_icu && skia_use_harfbuzz) { sources = skparagraph_sources
sources = skparagraph_sources
configs += [ "../../third_party/icu/config:no_cxx" ]
} else {
sources = []
}
deps = [ deps = [
"../..:skia", "../..:skia",
"../skshaper", "../skshaper",
"//third_party/icu",
] ]
} }
@ -43,21 +39,15 @@ if (skia_enable_skparagraph) {
import("skparagraph.gni") import("skparagraph.gni")
public_configs = [ ":utils_config" ] public_configs = [ ":utils_config" ]
configs += [ "../../:skia_private" ] configs += [ "../../:skia_private" ]
if (skia_use_icu && skia_use_harfbuzz) { sources = skparagraph_utils
sources = skparagraph_utils
configs += [ "../../third_party/icu/config:no_cxx" ]
} else {
sources = []
}
deps = [ deps = [
"../..:skia", "../..:skia",
"../skshaper", "../skshaper",
"//third_party/icu",
] ]
} }
source_set("gm") { source_set("gm") {
if (skia_use_icu && skia_use_harfbuzz && paragraph_gms_enabled) { if (paragraph_gms_enabled) {
testonly = true testonly = true
sources = [ "gm/simple_gm.cpp" ] sources = [ "gm/simple_gm.cpp" ]
deps = [ deps = [
@ -65,53 +55,63 @@ if (skia_enable_skparagraph) {
"../..:gpu_tool_utils", "../..:gpu_tool_utils",
"../..:skia", "../..:skia",
"../skshaper", "../skshaper",
"//third_party/icu",
] ]
} else {
sources = []
} }
} }
source_set("tests") { source_set("tests") {
if (skia_use_icu && skia_use_harfbuzz && paragraph_tests_enabled) { if (paragraph_tests_enabled) {
testonly = true testonly = true
sources = [ "tests/SkParagraphTest.cpp" ] sources = [ "tests/SkParagraphTest.cpp" ]
configs += [ "../../third_party/icu/config:no_cxx" ]
deps = [ deps = [
":skparagraph", ":skparagraph",
"../..:gpu_tool_utils", "../..:gpu_tool_utils",
"../..:skia", "../..:skia",
"../skshaper", "../skshaper",
"//third_party/icu",
] ]
} else {
sources = []
} }
} }
source_set("bench") { source_set("bench") {
if (skia_use_icu && skia_use_harfbuzz && paragraph_bench_enabled) { if (paragraph_bench_enabled) {
testonly = true testonly = true
sources = [ "bench/ParagraphBench.cpp" ] sources = [ "bench/ParagraphBench.cpp" ]
configs += [ "../../third_party/icu/config:no_cxx" ]
deps = [ deps = [
":skparagraph", ":skparagraph",
"../..:skia", "../..:skia",
"../skshaper", "../skshaper",
"//third_party/icu",
] ]
} else {
sources = []
} }
} }
source_set("samples") { source_set("samples") {
if (skia_use_icu && skia_use_harfbuzz) { testonly = true
testonly = true sources = [ "samples/SampleParagraph.cpp" ]
sources = [ "samples/SampleParagraph.cpp" ] deps = [
configs += [ "../../third_party/icu/config:no_cxx" ] ":skparagraph",
deps = [ ":utils",
":skparagraph", "../..:skia",
":utils", "../skshaper",
"../..:skia", ]
"../skshaper",
"//third_party/icu",
]
}
} }
} }
} else {
group("skparagraph") {
}
group("utils") {
}
group("gm") {
}
group("tests") {
}
group("bench") {
}
group("samples") {
}
} }

View File

@ -21,7 +21,7 @@
#include "tools/ToolUtils.h" #include "tools/ToolUtils.h"
#include "modules/skparagraph/include/Paragraph.h" #include "modules/skparagraph/include/Paragraph.h"
#include "modules/skparagraph/include/ParagraphBuilder.h" #include "modules/skparagraph/src/ParagraphBuilderImpl.h"
static const char* gSpeach = "Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity."; static const char* gSpeach = "Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity.";
@ -57,7 +57,11 @@ public:
auto collection = sk_make_sp<skia::textlayout::FontCollection>(); auto collection = sk_make_sp<skia::textlayout::FontCollection>();
collection->setDefaultFontManager(SkFontMgr::RefDefault()); collection->setDefaultFontManager(SkFontMgr::RefDefault());
auto builder = skia::textlayout::ParagraphBuilder::make(paraStyle, collection); auto builder = skia::textlayout::ParagraphBuilderImpl::make(paraStyle, collection);
if (nullptr == builder) {
fPara = nullptr;
return;
}
builder->addText(gSpeach, strlen(gSpeach)); builder->addText(gSpeach, strlen(gSpeach));
@ -81,6 +85,9 @@ protected:
SkISize onISize() override { return SkISize::Make(412, 420); } SkISize onISize() override { return SkISize::Make(412, 420); }
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
if (nullptr == fPara) {
return DrawResult::kSkip;
}
const int loop = (this->getMode() == kGM_Mode) ? 1 : 50; const int loop = (this->getMode() == kGM_Mode) ? 1 : 50;
int parity = 0; int parity = 0;

View File

@ -57,6 +57,8 @@ public:
// Constructs a SkParagraph object that can be used to layout and paint the text to a SkCanvas. // Constructs a SkParagraph object that can be used to layout and paint the text to a SkCanvas.
virtual std::unique_ptr<Paragraph> Build() = 0; virtual std::unique_ptr<Paragraph> Build() = 0;
// Just until we fix all the google3 code
static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style, static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style,
sk_sp<FontCollection> fontCollection); sk_sp<FontCollection> fontCollection);
}; };

View File

@ -72,7 +72,9 @@ struct ParagraphStyle {
ParagraphStyle(); ParagraphStyle();
bool operator==(const ParagraphStyle& rhs) const { bool operator==(const ParagraphStyle& rhs) const {
return this->fHeight == rhs.fHeight && this->fEllipsis == rhs.fEllipsis && return this->fHeight == rhs.fHeight &&
this->fEllipsis == rhs.fEllipsis &&
this->fEllipsisUtf16 == rhs.fEllipsisUtf16 &&
this->fTextDirection == rhs.fTextDirection && this->fTextAlign == rhs.fTextAlign && this->fTextDirection == rhs.fTextDirection && this->fTextAlign == rhs.fTextAlign &&
this->fDefaultTextStyle == rhs.fDefaultTextStyle; this->fDefaultTextStyle == rhs.fDefaultTextStyle;
} }
@ -92,8 +94,9 @@ struct ParagraphStyle {
size_t getMaxLines() const { return fLinesLimit; } size_t getMaxLines() const { return fLinesLimit; }
void setMaxLines(size_t maxLines) { fLinesLimit = maxLines; } void setMaxLines(size_t maxLines) { fLinesLimit = maxLines; }
const SkString& getEllipsis() const { return fEllipsis; } SkString getEllipsis() const { return fEllipsis; }
void setEllipsis(const std::u16string& ellipsis); std::u16string getEllipsisUtf16() const { return fEllipsisUtf16; }
void setEllipsis(const std::u16string& ellipsis) { fEllipsisUtf16 = ellipsis; }
void setEllipsis(const SkString& ellipsis) { fEllipsis = ellipsis; } void setEllipsis(const SkString& ellipsis) { fEllipsis = ellipsis; }
SkScalar getHeight() const { return fHeight; } SkScalar getHeight() const { return fHeight; }
@ -105,7 +108,7 @@ struct ParagraphStyle {
bool unlimited_lines() const { bool unlimited_lines() const {
return fLinesLimit == std::numeric_limits<size_t>::max(); return fLinesLimit == std::numeric_limits<size_t>::max();
} }
bool ellipsized() const { return fEllipsis.size() != 0; } bool ellipsized() const { return !fEllipsis.isEmpty() || !fEllipsisUtf16.empty(); }
TextAlign effective_align() const; TextAlign effective_align() const;
bool hintingIsOn() const { return fHintingIsOn; } bool hintingIsOn() const { return fHintingIsOn; }
void turnHintingOff() { fHintingIsOn = false; } void turnHintingOff() { fHintingIsOn = false; }
@ -118,6 +121,7 @@ private:
TextAlign fTextAlign; TextAlign fTextAlign;
TextDirection fTextDirection; TextDirection fTextDirection;
size_t fLinesLimit; size_t fLinesLimit;
std::u16string fEllipsisUtf16;
SkString fEllipsis; SkString fEllipsis;
SkScalar fHeight; SkScalar fHeight;
TextHeightBehavior fTextHeightBehavior; TextHeightBehavior fTextHeightBehavior;

View File

@ -17,9 +17,9 @@
#include "modules/skparagraph/include/TypefaceFontProvider.h" #include "modules/skparagraph/include/TypefaceFontProvider.h"
#include "modules/skparagraph/src/ParagraphBuilderImpl.h" #include "modules/skparagraph/src/ParagraphBuilderImpl.h"
#include "modules/skparagraph/src/ParagraphImpl.h" #include "modules/skparagraph/src/ParagraphImpl.h"
#include "modules/skparagraph/src/ParagraphUtil.h"
#include "modules/skparagraph/src/TextLine.h" #include "modules/skparagraph/src/TextLine.h"
#include "modules/skparagraph/utils/TestFontCollection.h" #include "modules/skparagraph/utils/TestFontCollection.h"
#include "modules/skshaper/src/SkUnicode.h"
#include "samplecode/Sample.h" #include "samplecode/Sample.h"
#include "src/core/SkOSFile.h" #include "src/core/SkOSFile.h"
#include "src/shaders/SkColorShader.h" #include "src/shaders/SkColorShader.h"
@ -28,7 +28,6 @@
#include "tools/Resources.h" #include "tools/Resources.h"
#include "tools/flags/CommandLineFlags.h" #include "tools/flags/CommandLineFlags.h"
static DEFINE_bool(verboseParagraph, false, "paragraph samples very verbose."); static DEFINE_bool(verboseParagraph, false, "paragraph samples very verbose.");
using namespace skia::textlayout; using namespace skia::textlayout;
@ -746,14 +745,15 @@ protected:
builder.addText(text4); builder.addText(text4);
builder.pop(); builder.pop();
} else { } else {
if (this->isVerbose()) {
SkString str = SkStringFromU16String(text);
SkDebugf("Text: %s\n", str.c_str());
}
builder.addText(text + expected); builder.addText(text + expected);
} }
auto paragraph = builder.Build(); auto paragraph = builder.Build();
auto impl = static_cast<ParagraphImpl*>(paragraph.get());
if (this->isVerbose()) {
SkDebugf("Text: >%s<\n", impl->text().data());
}
paragraph->layout(w - margin * 2); paragraph->layout(w - margin * 2);
paragraph->paint(canvas, margin, margin); paragraph->paint(canvas, margin, margin);
} }
@ -1608,15 +1608,14 @@ protected:
ParagraphBuilderImpl builder(paragraph_style, fontCollection); ParagraphBuilderImpl builder(paragraph_style, fontCollection);
builder.pushStyle(text_style); builder.pushStyle(text_style);
auto utf16text = zalgo.zalgo("SkParagraph"); auto utf16text = zalgo.zalgo("SkParagraph");
if (this->isVerbose()) {
SkString str = SkStringFromU16String(utf16text);
SkDebugf("Text:>%s<\n", str.c_str());
}
builder.addText(utf16text); builder.addText(utf16text);
fParagraph = builder.Build(); fParagraph = builder.Build();
} }
auto impl = static_cast<ParagraphImpl*>(fParagraph.get()); auto impl = static_cast<ParagraphImpl*>(fParagraph.get());
if (this->isVerbose()) {
SkDebugf("Text:>%s<\n", impl->text().data());
}
impl->setState(InternalState::kUnknown); impl->setState(InternalState::kUnknown);
fParagraph->layout(1000); fParagraph->layout(1000);
fParagraph->paint(canvas, 300, 200); fParagraph->paint(canvas, 300, 200);

View File

@ -31,8 +31,6 @@ skparagraph_sources = [
"$_src/ParagraphImpl.cpp", "$_src/ParagraphImpl.cpp",
"$_src/ParagraphImpl.h", "$_src/ParagraphImpl.h",
"$_src/ParagraphStyle.cpp", "$_src/ParagraphStyle.cpp",
"$_src/ParagraphUtil.cpp",
"$_src/ParagraphUtil.h",
"$_src/Run.cpp", "$_src/Run.cpp",
"$_src/Run.h", "$_src/Run.h",
"$_src/TextLine.cpp", "$_src/TextLine.cpp",

View File

@ -2,10 +2,15 @@
#include "modules/skparagraph/src/Iterators.h" #include "modules/skparagraph/src/Iterators.h"
#include "modules/skparagraph/src/OneLineShaper.h" #include "modules/skparagraph/src/OneLineShaper.h"
#include "modules/skparagraph/src/ParagraphUtil.h" #include "src/utils/SkUTF.h"
#include <algorithm> #include <algorithm>
#include <unordered_set> #include <unordered_set>
static inline SkUnichar nextUtf8Unit(const char** ptr, const char* end) {
SkUnichar val = SkUTF::NextUTF8(ptr, end);
return val < 0 ? 0xFFFD : val;
}
namespace skia { namespace skia {
namespace textlayout { namespace textlayout {
@ -297,8 +302,8 @@ void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnres
const char* cluster = text.begin() + clusterIndex(i); const char* cluster = text.begin() + clusterIndex(i);
SkUnichar codepoint = nextUtf8Unit(&cluster, text.end()); SkUnichar codepoint = nextUtf8Unit(&cluster, text.end());
bool isControl8 = isControl(codepoint); bool isControl8 = fParagraph->getUnicode()->isControl(codepoint);
bool isWhitespace8 = isWhitespace(codepoint); bool isWhitespace8 = fParagraph->getUnicode()->isWhitespace(codepoint);
// Inspect the glyph // Inspect the glyph
auto glyph = fCurrentRun->fGlyphs[i]; auto glyph = fCurrentRun->fGlyphs[i];

View File

@ -8,24 +8,50 @@
#include "modules/skparagraph/include/TextStyle.h" #include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/ParagraphBuilderImpl.h" #include "modules/skparagraph/src/ParagraphBuilderImpl.h"
#include "modules/skparagraph/src/ParagraphImpl.h" #include "modules/skparagraph/src/ParagraphImpl.h"
#include "modules/skparagraph/src/ParagraphUtil.h"
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include "src/core/SkStringUtils.h"
namespace skia { namespace skia {
namespace textlayout { namespace textlayout {
std::unique_ptr<ParagraphBuilder> ParagraphBuilder::make( std::unique_ptr<ParagraphBuilder> ParagraphBuilder::make(
const ParagraphStyle& style, sk_sp<FontCollection> fontCollection) { const ParagraphStyle& style, sk_sp<FontCollection> fontCollection) {
return ParagraphBuilderImpl::make(style, fontCollection);
}
std::unique_ptr<ParagraphBuilder> ParagraphBuilderImpl::make(
const ParagraphStyle& style, sk_sp<FontCollection> fontCollection) {
auto unicode = SkUnicode::Make();
if (nullptr == unicode) {
return nullptr;
}
return std::make_unique<ParagraphBuilderImpl>(style, fontCollection); return std::make_unique<ParagraphBuilderImpl>(style, fontCollection);
} }
std::unique_ptr<ParagraphBuilder> ParagraphBuilderImpl::make(
const ParagraphStyle& style, sk_sp<FontCollection> fontCollection, std::unique_ptr<SkUnicode> unicode) {
if (nullptr == unicode) {
return nullptr;
}
return std::make_unique<ParagraphBuilderImpl>(style, fontCollection, std::move(unicode));
}
ParagraphBuilderImpl::ParagraphBuilderImpl(
const ParagraphStyle& style, sk_sp<FontCollection> fontCollection, std::unique_ptr<SkUnicode> unicode)
: ParagraphBuilder(style, fontCollection)
, fUtf8()
, fFontCollection(std::move(fontCollection))
, fUnicode(std::move(unicode)) {
SkASSERT(fUnicode);
this->setParagraphStyle(style);
}
ParagraphBuilderImpl::ParagraphBuilderImpl( ParagraphBuilderImpl::ParagraphBuilderImpl(
const ParagraphStyle& style, sk_sp<FontCollection> fontCollection) const ParagraphStyle& style, sk_sp<FontCollection> fontCollection)
: ParagraphBuilder(style, fontCollection), fUtf8(), fFontCollection(std::move(fontCollection)) { : ParagraphBuilderImpl(style, fontCollection, SkUnicode::Make())
this->setParagraphStyle(style); { }
}
ParagraphBuilderImpl::~ParagraphBuilderImpl() = default; ParagraphBuilderImpl::~ParagraphBuilderImpl() = default;
@ -74,7 +100,8 @@ TextStyle ParagraphBuilderImpl::peekStyle() {
} }
void ParagraphBuilderImpl::addText(const std::u16string& text) { void ParagraphBuilderImpl::addText(const std::u16string& text) {
fUtf8.append(SkStringFromU16String(text)); auto utf8 = fUnicode->convertUtf16ToUtf8(text);
fUtf8.append(utf8);
} }
void ParagraphBuilderImpl::addText(const char* text) { void ParagraphBuilderImpl::addText(const char* text) {
@ -128,7 +155,7 @@ std::unique_ptr<Paragraph> ParagraphBuilderImpl::Build() {
// Add one fake placeholder with the rest of the text // Add one fake placeholder with the rest of the text
addPlaceholder(PlaceholderStyle(), true); addPlaceholder(PlaceholderStyle(), true);
return std::make_unique<ParagraphImpl>( return std::make_unique<ParagraphImpl>(
fUtf8, fParagraphStyle, fStyledBlocks, fPlaceholders, fFontCollection); fUtf8, fParagraphStyle, fStyledBlocks, fPlaceholders, fFontCollection, std::move(fUnicode));
} }
} // namespace textlayout } // namespace textlayout

View File

@ -11,12 +11,18 @@
#include "modules/skparagraph/include/ParagraphBuilder.h" #include "modules/skparagraph/include/ParagraphBuilder.h"
#include "modules/skparagraph/include/ParagraphStyle.h" #include "modules/skparagraph/include/ParagraphStyle.h"
#include "modules/skparagraph/include/TextStyle.h" #include "modules/skparagraph/include/TextStyle.h"
#include "modules/skshaper/src/SkUnicode.h"
namespace skia { namespace skia {
namespace textlayout { namespace textlayout {
class ParagraphBuilderImpl : public ParagraphBuilder { class ParagraphBuilderImpl : public ParagraphBuilder {
public: public:
ParagraphBuilderImpl(const ParagraphStyle& style,
sk_sp<FontCollection> fontCollection,
std::unique_ptr<SkUnicode> unicode);
// Just until we fix all the code; calls icu::make inside
ParagraphBuilderImpl(const ParagraphStyle& style, sk_sp<FontCollection> fontCollection); ParagraphBuilderImpl(const ParagraphStyle& style, sk_sp<FontCollection> fontCollection);
~ParagraphBuilderImpl() override; ~ParagraphBuilderImpl() override;
@ -55,6 +61,13 @@ public:
// Constructs a SkParagraph object that can be used to layout and paint the text to a SkCanvas. // Constructs a SkParagraph object that can be used to layout and paint the text to a SkCanvas.
std::unique_ptr<Paragraph> Build() override; std::unique_ptr<Paragraph> Build() override;
static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style,
sk_sp<FontCollection> fontCollection,
std::unique_ptr<SkUnicode> unicode);
// Just until we fix all the code; calls icu::make inside
static std::unique_ptr<ParagraphBuilder> make(const ParagraphStyle& style,
sk_sp<FontCollection> fontCollection);
private: private:
void endRunIfNeeded(); void endRunIfNeeded();
void addPlaceholder(const PlaceholderStyle& placeholderStyle, bool lastOne); void addPlaceholder(const PlaceholderStyle& placeholderStyle, bool lastOne);
@ -65,6 +78,8 @@ private:
SkTArray<Placeholder, true> fPlaceholders; SkTArray<Placeholder, true> fPlaceholders;
sk_sp<FontCollection> fFontCollection; sk_sp<FontCollection> fFontCollection;
ParagraphStyle fParagraphStyle; ParagraphStyle fParagraphStyle;
std::unique_ptr<SkUnicode> fUnicode;
}; };
} // namespace textlayout } // namespace textlayout
} // namespace skia } // namespace skia

View File

@ -13,17 +13,11 @@
#include "modules/skparagraph/include/TextStyle.h" #include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/OneLineShaper.h" #include "modules/skparagraph/src/OneLineShaper.h"
#include "modules/skparagraph/src/ParagraphImpl.h" #include "modules/skparagraph/src/ParagraphImpl.h"
#include "modules/skparagraph/src/ParagraphUtil.h"
#include "modules/skparagraph/src/Run.h" #include "modules/skparagraph/src/Run.h"
#include "modules/skparagraph/src/TextLine.h" #include "modules/skparagraph/src/TextLine.h"
#include "modules/skparagraph/src/TextWrapper.h" #include "modules/skparagraph/src/TextWrapper.h"
#include "src/core/SkSpan.h" #include "src/core/SkSpan.h"
#include "src/utils/SkUTF.h" #include "src/utils/SkUTF.h"
#if defined(SK_USING_THIRD_PARTY_ICU)
#include "third_party/icu/SkLoadICU.h"
#endif
#include <math.h> #include <math.h>
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
@ -71,7 +65,8 @@ ParagraphImpl::ParagraphImpl(const SkString& text,
ParagraphStyle style, ParagraphStyle style,
SkTArray<Block, true> blocks, SkTArray<Block, true> blocks,
SkTArray<Placeholder, true> placeholders, SkTArray<Placeholder, true> placeholders,
sk_sp<FontCollection> fonts) sk_sp<FontCollection> fonts,
std::unique_ptr<SkUnicode> unicode)
: Paragraph(std::move(style), std::move(fonts)) : Paragraph(std::move(style), std::move(fonts))
, fTextStyles(std::move(blocks)) , fTextStyles(std::move(blocks))
, fPlaceholders(std::move(placeholders)) , fPlaceholders(std::move(placeholders))
@ -81,21 +76,28 @@ ParagraphImpl::ParagraphImpl(const SkString& text,
, fPicture(nullptr) , fPicture(nullptr)
, fStrutMetrics(false) , fStrutMetrics(false)
, fOldWidth(0) , fOldWidth(0)
, fOldHeight(0) { , fOldHeight(0)
fICU = SkUnicode::Make(); , fUnicode(std::move(unicode))
{
SkASSERT(fUnicode);
} }
ParagraphImpl::ParagraphImpl(const std::u16string& utf16text, ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
ParagraphStyle style, ParagraphStyle style,
SkTArray<Block, true> blocks, SkTArray<Block, true> blocks,
SkTArray<Placeholder, true> placeholders, SkTArray<Placeholder, true> placeholders,
sk_sp<FontCollection> fonts) sk_sp<FontCollection> fonts,
: ParagraphImpl(SkStringFromU16String(utf16text), std::unique_ptr<SkUnicode> unicode)
: ParagraphImpl(SkString(),
std::move(style), std::move(style),
std::move(blocks), std::move(blocks),
std::move(placeholders), std::move(placeholders),
std::move(fonts)) std::move(fonts),
{ } std::move(unicode))
{
SkASSERT(fUnicode);
fText = fUnicode->convertUtf16ToUtf8(utf16text);
}
ParagraphImpl::~ParagraphImpl() = default; ParagraphImpl::~ParagraphImpl() = default;
@ -243,26 +245,23 @@ void ParagraphImpl::resetContext() {
} }
// shapeTextIntoEndlessLine is the thing that calls this method // shapeTextIntoEndlessLine is the thing that calls this method
// (that contains all ICU dependencies except for words)
bool ParagraphImpl::computeCodeUnitProperties() { bool ParagraphImpl::computeCodeUnitProperties() {
#if defined(SK_USING_THIRD_PARTY_ICU) if (nullptr == fUnicode) {
if (!SkLoadICU()) {
return false; return false;
} }
#endif
// Get bidi regions // Get bidi regions
auto textDirection = fParagraphStyle.getTextDirection() == TextDirection::kLtr auto textDirection = fParagraphStyle.getTextDirection() == TextDirection::kLtr
? SkUnicode::TextDirection::kLTR ? SkUnicode::TextDirection::kLTR
: SkUnicode::TextDirection::kRTL; : SkUnicode::TextDirection::kRTL;
if (!fICU->getBidiRegions(fText.c_str(), fText.size(), textDirection, &fBidiRegions)) { if (!fUnicode->getBidiRegions(fText.c_str(), fText.size(), textDirection, &fBidiRegions)) {
return false; return false;
} }
// Get white spaces // Get white spaces
std::vector<SkUnicode::Position> whitespaces; std::vector<SkUnicode::Position> whitespaces;
if (!fICU->getWhitespaces(fText.c_str(), fText.size(), &whitespaces)) { if (!fUnicode->getWhitespaces(fText.c_str(), fText.size(), &whitespaces)) {
return false; return false;
} }
for (auto whitespace : whitespaces) { for (auto whitespace : whitespaces) {
@ -271,7 +270,7 @@ bool ParagraphImpl::computeCodeUnitProperties() {
// Get line breaks // Get line breaks
std::vector<SkUnicode::LineBreakBefore> lineBreaks; std::vector<SkUnicode::LineBreakBefore> lineBreaks;
if (!fICU->getLineBreaks(fText.c_str(), fText.size(), &lineBreaks)) { if (!fUnicode->getLineBreaks(fText.c_str(), fText.size(), &lineBreaks)) {
return false; return false;
} }
for (auto& lineBreak : lineBreaks) { for (auto& lineBreak : lineBreaks) {
@ -282,7 +281,7 @@ bool ParagraphImpl::computeCodeUnitProperties() {
// Get graphemes // Get graphemes
std::vector<SkUnicode::Position> graphemes; std::vector<SkUnicode::Position> graphemes;
if (!fICU->getGraphemes(fText.c_str(), fText.size(), &graphemes)) { if (!fUnicode->getGraphemes(fText.c_str(), fText.size(), &graphemes)) {
return false; return false;
} }
for (auto pos : graphemes) { for (auto pos : graphemes) {
@ -429,7 +428,7 @@ void ParagraphImpl::breakShapedTextIntoLines(SkScalar maxWidth) {
// TODO: Take in account clipped edges // TODO: Take in account clipped edges
auto& line = this->addLine(offset, advance, text, textWithSpaces, clusters, clustersWithGhosts, widthWithSpaces, metrics); auto& line = this->addLine(offset, advance, text, textWithSpaces, clusters, clustersWithGhosts, widthWithSpaces, metrics);
if (addEllipsis) { if (addEllipsis) {
line.createEllipsis(maxWidth, fParagraphStyle.getEllipsis(), true); line.createEllipsis(maxWidth, getEllipsis(), true);
} }
fLongestLine = std::max(fLongestLine, nearlyZero(advance.fX) ? widthWithSpaces : advance.fX); fLongestLine = std::max(fLongestLine, nearlyZero(advance.fX) ? widthWithSpaces : advance.fX);
@ -686,7 +685,7 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
SkRange<size_t> ParagraphImpl::getWordBoundary(unsigned offset) { SkRange<size_t> ParagraphImpl::getWordBoundary(unsigned offset) {
if (fWords.empty()) { if (fWords.empty()) {
if (!fICU->getWords(fText.c_str(), fText.size(), &fWords)) { if (!fUnicode->getWords(fText.c_str(), fText.size(), &fWords)) {
return {0, 0 }; return {0, 0 };
} }
} }
@ -837,6 +836,17 @@ void ParagraphImpl::computeEmptyMetrics() {
} }
} }
SkString ParagraphImpl::getEllipsis() const {
auto ellipsis8 = fParagraphStyle.getEllipsis();
auto ellipsis16 = fParagraphStyle.getEllipsisUtf16();
if (!ellipsis8.isEmpty()) {
return ellipsis8;
} else {
return fUnicode->convertUtf16ToUtf8(fParagraphStyle.getEllipsisUtf16());
}
}
void ParagraphImpl::updateText(size_t from, SkString text) { void ParagraphImpl::updateText(size_t from, SkString text) {
fText.remove(from, from + text.size()); fText.remove(from, from + text.size());
fText.insert(from, text); fText.insert(from, text);

View File

@ -100,13 +100,15 @@ public:
ParagraphStyle style, ParagraphStyle style,
SkTArray<Block, true> blocks, SkTArray<Block, true> blocks,
SkTArray<Placeholder, true> placeholders, SkTArray<Placeholder, true> placeholders,
sk_sp<FontCollection> fonts); sk_sp<FontCollection> fonts,
std::unique_ptr<SkUnicode> unicode);
ParagraphImpl(const std::u16string& utf16text, ParagraphImpl(const std::u16string& utf16text,
ParagraphStyle style, ParagraphStyle style,
SkTArray<Block, true> blocks, SkTArray<Block, true> blocks,
SkTArray<Placeholder, true> placeholders, SkTArray<Placeholder, true> placeholders,
sk_sp<FontCollection> fonts); sk_sp<FontCollection> fonts,
std::unique_ptr<SkUnicode> unicode);
~ParagraphImpl() override; ~ParagraphImpl() override;
void layout(SkScalar width) override; void layout(SkScalar width) override;
@ -155,6 +157,8 @@ public:
} }
InternalLineMetrics strutMetrics() const { return fStrutMetrics; } InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
SkString getEllipsis() const;
SkSpan<const char> text(TextRange textRange); SkSpan<const char> text(TextRange textRange);
SkSpan<Cluster> clusters(ClusterRange clusterRange); SkSpan<Cluster> clusters(ClusterRange clusterRange);
Cluster& cluster(ClusterIndex clusterIndex); Cluster& cluster(ClusterIndex clusterIndex);
@ -218,7 +222,7 @@ public:
bool codeUnitHasProperty(size_t index, CodeUnitFlags property) const { return (fCodeUnitProperties[index] & property) == property; } bool codeUnitHasProperty(size_t index, CodeUnitFlags property) const { return (fCodeUnitProperties[index] & property) == property; }
SkUnicode* getICU() { return fICU.get(); } SkUnicode* getUnicode() { return fUnicode.get(); }
private: private:
friend class ParagraphBuilder; friend class ParagraphBuilder;
@ -268,7 +272,7 @@ private:
SkScalar fOldHeight; SkScalar fOldHeight;
SkScalar fMaxWidthWithTrailingSpaces; SkScalar fMaxWidthWithTrailingSpaces;
std::unique_ptr<SkUnicode> fICU; std::unique_ptr<SkUnicode> fUnicode;
}; };
} // namespace textlayout } // namespace textlayout
} // namespace skia } // namespace skia

View File

@ -2,7 +2,9 @@
#include "modules/skparagraph/include/DartTypes.h" #include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/ParagraphStyle.h" #include "modules/skparagraph/include/ParagraphStyle.h"
#include "modules/skparagraph/src/ParagraphUtil.h" #include "modules/skshaper/src/SkUnicode.h"
#include "src/core/SkStringUtils.h"
#include "src/utils/SkUTF.h"
namespace skia { namespace skia {
namespace textlayout { namespace textlayout {
@ -35,9 +37,5 @@ TextAlign ParagraphStyle::effective_align() const {
return fTextAlign; return fTextAlign;
} }
} }
void ParagraphStyle::setEllipsis(const std::u16string& ellipsis) {
fEllipsis = SkStringFromU16String(ellipsis);
}
} // namespace textlayout } // namespace textlayout
} // namespace skia } // namespace skia

View File

@ -1,49 +0,0 @@
// Copyright 2019 Google LLC.
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTo.h"
#include "modules/skparagraph/src/ParagraphUtil.h"
#include "src/utils/SkUTF.h"
#include <unicode/umachine.h>
#include <unicode/uchar.h>
#include <unicode/ustring.h>
#include <unicode/utypes.h>
#include <string>
namespace skia {
namespace textlayout {
SkString SkStringFromU16String(const std::u16string& utf16text) {
SkString dst;
UErrorCode status = U_ZERO_ERROR;
int32_t dstSize;
// Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
u_strToUTF8(nullptr, 0, &dstSize, (UChar*)utf16text.data(), SkToS32(utf16text.size()), &status);
dst.resize(dstSize);
status = U_ZERO_ERROR;
u_strToUTF8(dst.writable_str(), dst.size(), nullptr,
(UChar*)utf16text.data(), SkToS32(utf16text.size()), &status);
if (U_FAILURE(status)) {
SkDEBUGF("Invalid UTF-16 input: %s", u_errorName(status));
return dst;
}
return dst;
}
SkUnichar nextUtf8Unit(const char** ptr, const char* end) {
SkUnichar val = SkUTF::NextUTF8(ptr, end);
return val < 0 ? 0xFFFD : val;
}
bool isControl(SkUnichar utf8) {
return u_iscntrl(utf8);
}
bool isWhitespace(SkUnichar utf8) {
return u_isWhitespace(utf8);
}
} // namespace textlayout
} // namespace skia

View File

@ -1,17 +0,0 @@
// Copyright 2020 Google LLC.
#ifndef ParagraphUtil_DEFINED
#define ParagraphUtil_DEFINED
#include "include/core/SkString.h"
#include <string>
namespace skia {
namespace textlayout {
SkString SkStringFromU16String(const std::u16string& utf16text);
SkUnichar nextUtf8Unit(const char** ptr, const char* end);
bool isControl(SkUnichar utf8);
bool isWhitespace(SkUnichar utf8);
} // namespace textlayout
} // namespace skia
#endif

View File

@ -144,7 +144,7 @@ TextLine::TextLine(ParagraphImpl* owner,
SkAutoSTArray<kPreallocCount, int32_t> logicalOrder(numRuns); SkAutoSTArray<kPreallocCount, int32_t> logicalOrder(numRuns);
// TODO: hide all these logic in SkUnicode? // TODO: hide all these logic in SkUnicode?
fOwner->getICU()->reorderVisual(runLevels.data(), numRuns, logicalOrder.data()); fOwner->getUnicode()->reorderVisual(runLevels.data(), numRuns, logicalOrder.data());
auto firstRunIndex = start.runIndex(); auto firstRunIndex = start.runIndex();
for (auto index : logicalOrder) { for (auto index : logicalOrder) {
fRunsInVisualOrder.push_back(firstRunIndex + index); fRunsInVisualOrder.push_back(firstRunIndex + index);

View File

@ -224,11 +224,10 @@ void TextWrapper::breakTextIntoLines(ParagraphImpl* parent,
return; return;
} }
auto maxLines = parent->paragraphStyle().getMaxLines(); auto maxLines = parent->paragraphStyle().getMaxLines();
auto& ellipsisStr = parent->paragraphStyle().getEllipsis();
auto align = parent->paragraphStyle().effective_align(); auto align = parent->paragraphStyle().effective_align();
auto unlimitedLines = maxLines == std::numeric_limits<size_t>::max(); auto unlimitedLines = maxLines == std::numeric_limits<size_t>::max();
auto endlessLine = !SkScalarIsFinite(maxWidth); auto endlessLine = !SkScalarIsFinite(maxWidth);
auto hasEllipsis = !ellipsisStr.isEmpty(); auto hasEllipsis = parent->paragraphStyle().ellipsized();
SkScalar softLineMaxIntrinsicWidth = 0; SkScalar softLineMaxIntrinsicWidth = 0;
fEndLine = TextStretch(span.begin(), span.begin(), parent->strutForceHeight()); fEndLine = TextStretch(span.begin(), span.begin(), parent->strutForceHeight());

View File

@ -4,10 +4,7 @@
# found in the LICENSE file. # found in the LICENSE file.
import("../../gn/skia.gni") import("../../gn/skia.gni")
import("skshaper.gni")
declare_args() {
skia_enable_skshaper = true
}
if (skia_enable_skshaper) { if (skia_enable_skshaper) {
config("public_config") { config("public_config") {
@ -27,7 +24,6 @@ if (skia_enable_skshaper) {
component("skshaper") { component("skshaper") {
check_includes = false check_includes = false
import("skshaper.gni")
public_configs = [ ":public_config" ] public_configs = [ ":public_config" ]
public = skia_shaper_public public = skia_shaper_public
deps = [ "../..:skia" ] deps = [ "../..:skia" ]

View File

@ -19,3 +19,7 @@ skia_shaper_icu_sources = [
] ]
skia_shaper_harfbuzz_sources = [ "$_src/SkShaper_harfbuzz.cpp" ] skia_shaper_harfbuzz_sources = [ "$_src/SkShaper_harfbuzz.cpp" ]
skia_shaper_coretext_sources = [ "$_src/SkShaper_coretext.cpp" ] skia_shaper_coretext_sources = [ "$_src/SkShaper_coretext.cpp" ]
declare_args() {
skia_enable_skshaper = true
}

View File

@ -9,6 +9,7 @@
#include "include/core/SkTypes.h" #include "include/core/SkTypes.h"
#include "src/core/SkSpan.h" #include "src/core/SkSpan.h"
#include "src/utils/SkUTF.h"
#include <vector> #include <vector>
#if !defined(SKUNICODE_IMPLEMENTATION) #if !defined(SKUNICODE_IMPLEMENTATION)
@ -89,6 +90,10 @@ class SKUNICODE_API SkUnicode {
virtual ~SkUnicode() = default; virtual ~SkUnicode() = default;
virtual bool isControl(SkUnichar utf8) = 0;
virtual bool isWhitespace(SkUnichar utf8) = 0;
virtual SkString convertUtf16ToUtf8(const std::u16string& utf16) = 0;
// Iterators (used in SkShaper) // Iterators (used in SkShaper)
virtual std::unique_ptr<SkBidiIterator> makeBidiIterator virtual std::unique_ptr<SkBidiIterator> makeBidiIterator
(const uint16_t text[], int count, SkBidiIterator::Direction) = 0; (const uint16_t text[], int count, SkBidiIterator::Direction) = 0;

View File

@ -4,17 +4,23 @@
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "include/core/SkString.h"
#include "include/private/SkTFitsIn.h" #include "include/private/SkTFitsIn.h"
#include "include/private/SkTemplates.h" #include "include/private/SkTemplates.h"
#include "modules/skshaper/src/SkUnicode.h" #include "modules/skshaper/src/SkUnicode.h"
#include "src/utils/SkUTF.h" #include "src/utils/SkUTF.h"
#include <unicode/ubidi.h> #include <unicode/ubidi.h>
#include <unicode/ubrk.h> #include <unicode/ubrk.h>
#include <unicode/ustring.h>
#include <unicode/utext.h> #include <unicode/utext.h>
#include <unicode/utypes.h> #include <unicode/utypes.h>
#include <vector> #include <vector>
#include <functional> #include <functional>
#if defined(SK_USING_THIRD_PARTY_ICU)
#include "SkLoadICU.h"
#endif
using SkUnicodeBidi = std::unique_ptr<UBiDi, SkFunctionWrapper<decltype(ubidi_close), ubidi_close>>; using SkUnicodeBidi = std::unique_ptr<UBiDi, SkFunctionWrapper<decltype(ubidi_close), ubidi_close>>;
using ICUUText = std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>>; using ICUUText = std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>>;
using ICUBreakIterator = std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>>; using ICUBreakIterator = std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>>;
@ -125,23 +131,11 @@ class SkUnicode_icu : public SkUnicode {
} }
} }
static int convertUtf8ToUtf16(const char* utf8, size_t utf8Units, std::unique_ptr<uint16_t[]>* utf16) {
int utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Units);
if (utf16Units < 0) {
SkDEBUGF("Convert error: Invalid utf8 input");
return utf16Units;
}
*utf16 = std::unique_ptr<uint16_t[]>(new uint16_t[utf16Units]);
SkDEBUGCODE(int dstLen =) SkUTF::UTF8ToUTF16(utf16->get(), utf16Units, utf8, utf8Units);
SkASSERT(dstLen == utf16Units);
return utf16Units;
}
static bool extractBidi(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* bidiRegions) { static bool extractBidi(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* bidiRegions) {
// Convert to UTF16 since for now bidi iterator only operates on utf16 // Convert to UTF16 since for now bidi iterator only operates on utf16
std::unique_ptr<uint16_t[]> utf16; std::unique_ptr<uint16_t[]> utf16;
auto utf16Units = convertUtf8ToUtf16(utf8, utf8Units, &utf16); auto utf16Units = utf8ToUtf16(utf8, utf8Units, &utf16);
if (utf16Units < 0) { if (utf16Units < 0) {
return false; return false;
} }
@ -276,6 +270,29 @@ class SkUnicode_icu : public SkUnicode {
return true; return true;
} }
static int utf8ToUtf16(const char* utf8, size_t utf8Units, std::unique_ptr<uint16_t[]>* utf16) {
int utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Units);
if (utf16Units < 0) {
SkDEBUGF("Convert error: Invalid utf8 input");
return utf16Units;
}
*utf16 = std::unique_ptr<uint16_t[]>(new uint16_t[utf16Units]);
SkDEBUGCODE(int dstLen =) SkUTF::UTF8ToUTF16(utf16->get(), utf16Units, utf8, utf8Units);
SkASSERT(dstLen == utf16Units);
return utf16Units;
}
static int utf16ToUtf8(const uint16_t* utf16, size_t utf16Units, std::unique_ptr<char[]>* utf8) {
int utf8Units = SkUTF::UTF16ToUTF8(nullptr, 0, utf16, utf16Units);
if (utf8Units < 0) {
SkDEBUGF("Convert error: Invalid utf16 input");
return utf8Units;
}
*utf8 = std::unique_ptr<char[]>(new char[utf8Units]);
SkDEBUGCODE(int dstLen =) SkUTF::UTF16ToUTF8(utf8->get(), utf8Units, utf16, utf16Units);
SkASSERT(dstLen == utf8Units);
return utf8Units;
}
public: public:
~SkUnicode_icu() override { } ~SkUnicode_icu() override { }
std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count, std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count,
@ -287,6 +304,25 @@ public:
return SkBidiIterator_icu::makeBidiIterator(text, count, dir); return SkBidiIterator_icu::makeBidiIterator(text, count, dir);
} }
// TODO: Use ICU data file to detect controls and whitespaces
bool isControl(SkUnichar utf8) override {
return u_iscntrl(utf8);
}
bool isWhitespace(SkUnichar utf8) override {
return u_isWhitespace(utf8);
}
SkString convertUtf16ToUtf8(const std::u16string& utf16) override {
std::unique_ptr<char[]> utf8;
auto utf8Units = SkUnicode_icu::utf16ToUtf8((uint16_t*)utf16.data(), utf16.size(), &utf8);
if (utf8Units >= 0) {
return SkString(utf8.get(), utf8Units);
} else {
return SkString();
}
}
bool getBidiRegions(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* results) override { bool getBidiRegions(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* results) override {
return extractBidi(utf8, utf8Units, dir, results); return extractBidi(utf8, utf8Units, dir, results);
} }
@ -305,7 +341,7 @@ public:
// Convert to UTF16 since we want the results in utf16 // Convert to UTF16 since we want the results in utf16
std::unique_ptr<uint16_t[]> utf16; std::unique_ptr<uint16_t[]> utf16;
auto utf16Units = convertUtf8ToUtf16(utf8, utf8Units, &utf16); auto utf16Units = utf8ToUtf16(utf8, utf8Units, &utf16);
if (utf16Units < 0) { if (utf16Units < 0) {
return false; return false;
} }
@ -330,4 +366,12 @@ public:
} }
}; };
std::unique_ptr<SkUnicode> SkUnicode::Make() { return std::make_unique<SkUnicode_icu>(); } std::unique_ptr<SkUnicode> SkUnicode::Make() {
#if defined(SK_USING_THIRD_PARTY_ICU)
if (!SkLoadICU()) {
SkDEBUGF("SkLoadICU() failed!\n");
return nullptr;
}
#endif
return std::make_unique<SkUnicode_icu>();
}

View File

@ -283,4 +283,28 @@ int SkUTF::UTF8ToUTF16(uint16_t dst[], int dstCapacity, const char src[], size_t
return dstLength; return dstLength;
} }
int SkUTF::UTF16ToUTF8(char dst[], int dstCapacity, const uint16_t src[], size_t srcLength) {
if (!dst) {
dstCapacity = 0;
}
int dstLength = 0;
const char* endDst = dst + dstCapacity;
for (size_t i = 0; i < srcLength; ++i) {
char utf8[SkUTF::kMaxBytesInUTF8Sequence];
size_t count = ToUTF8(src[i], utf8);
if (count == 0) {
return -1;
}
dstLength += count;
if (dst) {
const char* elems = utf8;
while (dst < endDst && count > 0) {
*dst++ = *elems++;
count -= 1;
}
}
}
return dstLength;
}

View File

@ -6,6 +6,7 @@
#include "include/core/SkTypes.h" #include "include/core/SkTypes.h"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <memory>
typedef int32_t SkUnichar; typedef int32_t SkUnichar;
@ -70,6 +71,12 @@ SK_SPI size_t ToUTF16(SkUnichar uni, uint16_t utf16[2] = nullptr);
*/ */
SK_SPI int UTF8ToUTF16(uint16_t dst[], int dstCapacity, const char src[], size_t srcByteLength); SK_SPI int UTF8ToUTF16(uint16_t dst[], int dstCapacity, const char src[], size_t srcByteLength);
/** Returns the number of resulting UTF8 values needed to convert the src utf16 sequence.
* If dst is not null, it is filled with the corresponding values up to its capacity.
* If there is an error, -1 is returned and the dst[] buffer is undefined.
*/
SK_SPI int UTF16ToUTF8(char dst[], int dstCapacity, const uint16_t src[], size_t srcLength);
} // namespace SkUTF } // namespace SkUTF
#endif // SkUTF_DEFINED #endif // SkUTF_DEFINED

View File

@ -25,7 +25,7 @@ static void* win_mmap(const char* dataFile) {
struct FCloseWrapper { void operator()(FILE* f) { fclose(f); } }; struct FCloseWrapper { void operator()(FILE* f) { fclose(f); } };
std::unique_ptr<FILE, FCloseWrapper> stream(fopen(dataFile, "rb")); std::unique_ptr<FILE, FCloseWrapper> stream(fopen(dataFile, "rb"));
if (!stream) { if (!stream) {
fprintf(stderr, "SkIcuLoader: datafile missing.\n"); fprintf(stderr, "SkIcuLoader: datafile missing: %s.\n", dataFile);
return nullptr; return nullptr;
} }
int fileno = _fileno(stream.get()); int fileno = _fileno(stream.get());