Make SkShaper an interface.
The interface here is not ideal, but there will need to be some build
clean-up before it can be changed.
Change-Id: Ic4d55634405f4c8d9c194e4e6f368287c9669dcd
Reviewed-on: https://skia-review.googlesource.com/c/193036
Reviewed-by: Hal Canary <halcanary@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/modules/skottie/src/SkottieAdapter.cpp b/modules/skottie/src/SkottieAdapter.cpp
index 648a811..140a026 100644
--- a/modules/skottie/src/SkottieAdapter.cpp
+++ b/modules/skottie/src/SkottieAdapter.cpp
@@ -421,12 +421,12 @@
BlobMaker blobMaker(fText.fAlign);
const auto& push_line = [&](const char* start, const char* end) {
- SkShaper shaper;
- if (!shaper.good()) {
+ std::unique_ptr<SkShaper> shaper = SkShaper::Make();
+ if (!shaper) {
return;
}
- shaper.shape(&blobMaker, font, start, SkToSizeT(end - start), true, { 0, 0 }, SK_ScalarMax);
+ shaper->shape(&blobMaker, font, start, SkToSizeT(end - start), true, { 0, 0 }, SK_ScalarMax);
};
const auto& is_line_break = [](SkUnichar uch) {
diff --git a/modules/skshaper/BUILD.gn b/modules/skshaper/BUILD.gn
index 3db1b91d..468b40e 100644
--- a/modules/skshaper/BUILD.gn
+++ b/modules/skshaper/BUILD.gn
@@ -8,6 +8,10 @@
config("public_config") {
if (skia_enable_skshaper) {
include_dirs = [ "include" ]
+ defines = []
+ if (skia_use_icu) {
+ defines += [ "SK_SHAPER_HARFBUZZ_AVAILABLE" ]
+ }
}
}
@@ -19,10 +23,9 @@
deps = [
"../..:skia",
]
- if (!skia_use_icu) {
- sources = skia_shaper_primitive_sources
- } else {
- sources = skia_shaper_harfbuzz_sources
+ sources = skia_shaper_primitive_sources
+ if (skia_use_icu) {
+ sources += skia_shaper_harfbuzz_sources
deps += [
"//third_party/harfbuzz",
"//third_party/icu",
diff --git a/modules/skshaper/include/SkShaper.h b/modules/skshaper/include/SkShaper.h
index ce7b54f..854c368 100644
--- a/modules/skshaper/include/SkShaper.h
+++ b/modules/skshaper/include/SkShaper.h
@@ -25,8 +25,15 @@
*/
class SkShaper {
public:
+ static std::unique_ptr<SkShaper> MakePrimitive();
+ #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
+ static std::unique_ptr<SkShaper> MakeHarfBuzz();
+ #endif
+
+ static std::unique_ptr<SkShaper> Make();
+
SkShaper();
- ~SkShaper();
+ virtual ~SkShaper();
class RunHandler {
public:
@@ -55,21 +62,17 @@
virtual void commitLine() = 0;
};
- bool good() const;
- SkPoint shape(RunHandler* handler,
- const SkFont& srcFont,
- const char* utf8text,
- size_t textBytes,
- bool leftToRight,
- SkPoint point,
- SkScalar width) const;
+ virtual SkPoint shape(RunHandler* handler,
+ const SkFont& srcFont,
+ const char* utf8text,
+ size_t textBytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const = 0;
private:
SkShaper(const SkShaper&) = delete;
SkShaper& operator=(const SkShaper&) = delete;
-
- struct Impl;
- std::unique_ptr<Impl> fImpl;
};
/**
diff --git a/modules/skshaper/skshaper.gni b/modules/skshaper/skshaper.gni
index c0f5fd0..ed66e92 100644
--- a/modules/skshaper/skshaper.gni
+++ b/modules/skshaper/skshaper.gni
@@ -9,12 +9,8 @@
skia_shaper_public = [ "$_include/SkShaper.h" ]
-skia_shaper_harfbuzz_sources = [
- "$_src/SkShaper.cpp",
- "$_src/SkShaper_harfbuzz.cpp",
-]
-
skia_shaper_primitive_sources = [
"$_src/SkShaper.cpp",
"$_src/SkShaper_primitive.cpp",
]
+skia_shaper_harfbuzz_sources = [ "$_src/SkShaper_harfbuzz.cpp" ]
diff --git a/modules/skshaper/src/SkShaper.cpp b/modules/skshaper/src/SkShaper.cpp
index f476d21..f3e3929 100644
--- a/modules/skshaper/src/SkShaper.cpp
+++ b/modules/skshaper/src/SkShaper.cpp
@@ -9,6 +9,19 @@
#include "SkSpan.h"
#include "SkTextBlobPriv.h"
+std::unique_ptr<SkShaper> SkShaper::Make() {
+#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
+ std::unique_ptr<SkShaper> shaper = SkShaper::MakeHarfBuzz();
+ if (shaper) {
+ return shaper;
+ }
+#endif
+ return SkShaper::MakePrimitive();
+}
+
+SkShaper::SkShaper() {}
+SkShaper::~SkShaper() {}
+
SkShaper::RunHandler::Buffer SkTextBlobBuilderRunHandler::newRunBuffer(const RunInfo&,
const SkFont& font,
int glyphCount,
diff --git a/modules/skshaper/src/SkShaper_harfbuzz.cpp b/modules/skshaper/src/SkShaper_harfbuzz.cpp
index 99553da..b2e7116 100644
--- a/modules/skshaper/src/SkShaper_harfbuzz.cpp
+++ b/modules/skshaper/src/SkShaper_harfbuzz.cpp
@@ -10,6 +10,7 @@
#include "SkFontArguments.h"
#include "SkFontMetrics.h"
#include "SkFontMgr.h"
+#include "SkMakeUnique.h"
#include "SkMalloc.h"
#include "SkPoint.h"
#include "SkRefCnt.h"
@@ -786,12 +787,24 @@
} // namespace
-struct SkShaper::Impl {
+class SkShaperHarfBuzz : public SkShaper {
+public:
+ SkShaperHarfBuzz();
+ bool good() const;
+private:
HBBuffer fBuffer;
ICUBrk fLineBreakIterator;
ICUBrk fGraphemeBreakIterator;
- SkPoint shapeCorrect(RunHandler* handler,
+ SkPoint shape(SkShaper::RunHandler* handler,
+ const SkFont& srcFont,
+ const char* utf8text,
+ size_t textBytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const override;
+
+ SkPoint shapeCorrect(SkShaper::RunHandler* handler,
const char* utf8,
size_t utf8Bytes,
SkPoint point,
@@ -802,7 +815,7 @@
const ScriptRunIterator* script,
const FontRunIterator* font) const;
- SkPoint shapeOk(RunHandler* handler,
+ SkPoint shapeOk(SkShaper::RunHandler* handler,
const char* utf8,
size_t utf8Bytes,
SkPoint point,
@@ -823,24 +836,29 @@
const FontRunIterator* font) const;
};
-SkShaper::SkShaper() : fImpl(new Impl) {
+std::unique_ptr<SkShaper> SkShaper::MakeHarfBuzz() {
+ auto hb = skstd::make_unique<SkShaperHarfBuzz>();
+ return hb->good() ? std::move(hb) : nullptr;
+}
+
+SkShaperHarfBuzz::SkShaperHarfBuzz() {
#if defined(SK_USING_THIRD_PARTY_ICU)
if (!SkLoadICU()) {
SkDebugf("SkLoadICU() failed!\n");
return;
}
#endif
- fImpl->fBuffer.reset(hb_buffer_create());
- SkASSERT(fImpl->fBuffer);
+ fBuffer.reset(hb_buffer_create());
+ SkASSERT(fBuffer);
UErrorCode status = U_ZERO_ERROR;
- fImpl->fLineBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
+ fLineBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
if (U_FAILURE(status)) {
SkDebugf("Could not create line break iterator: %s", u_errorName(status));
SK_ABORT("");
}
- fImpl->fGraphemeBreakIterator.reset(ubrk_open(UBRK_CHARACTER, "th", nullptr, 0, &status));
+ fGraphemeBreakIterator.reset(ubrk_open(UBRK_CHARACTER, "th", nullptr, 0, &status));
if (U_FAILURE(status)) {
SkDebugf("Could not create grapheme break iterator: %s", u_errorName(status));
SK_ABORT("");
@@ -848,21 +866,19 @@
}
-SkShaper::~SkShaper() {}
-
-bool SkShaper::good() const {
- return fImpl->fBuffer &&
- fImpl->fLineBreakIterator &&
- fImpl->fGraphemeBreakIterator;
+bool SkShaperHarfBuzz::good() const {
+ return fBuffer &&
+ fLineBreakIterator &&
+ fGraphemeBreakIterator;
}
-SkPoint SkShaper::shape(RunHandler* handler,
- const SkFont& srcFont,
- const char* utf8,
- size_t utf8Bytes,
- bool leftToRight,
- SkPoint point,
- SkScalar width) const
+SkPoint SkShaperHarfBuzz::shape(SkShaper::RunHandler* handler,
+ const SkFont& srcFont,
+ const char* utf8,
+ size_t utf8Bytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const
{
SkASSERT(handler);
sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
@@ -884,7 +900,7 @@
}
runSegmenter.insert(language);
- hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
+ hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fBuffer.get());
SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
ScriptRunIterator* script = maybeScript.getMaybeNull();
if (!script) {
@@ -901,24 +917,24 @@
runSegmenter.insert(font);
if (true) {
- return fImpl->shapeCorrect(handler, utf8, utf8Bytes, point, width,
+ return shapeCorrect(handler, utf8, utf8Bytes, point, width,
runSegmenter, bidi, language, script, font);
} else {
- return fImpl->shapeOk(handler, utf8, utf8Bytes, point, width,
+ return shapeOk(handler, utf8, utf8Bytes, point, width,
runSegmenter, bidi, language, script, font);
}
}
-SkPoint SkShaper::Impl::shapeCorrect(RunHandler* handler,
- const char* utf8,
- size_t utf8Bytes,
- SkPoint point,
- SkScalar width,
- RunIteratorQueue& runSegmenter,
- const BiDiRunIterator* bidi,
- const LanguageRunIterator* language,
- const ScriptRunIterator* script,
- const FontRunIterator* font) const
+SkPoint SkShaperHarfBuzz::shapeCorrect(RunHandler* handler,
+ const char* utf8,
+ size_t utf8Bytes,
+ SkPoint point,
+ SkScalar width,
+ RunIteratorQueue& runSegmenter,
+ const BiDiRunIterator* bidi,
+ const LanguageRunIterator* language,
+ const ScriptRunIterator* script,
+ const FontRunIterator* font) const
{
ShapedLine line;
SkPoint currentPoint = point;
@@ -1064,16 +1080,16 @@
return currentPoint;
}
-SkPoint SkShaper::Impl::shapeOk(RunHandler* handler,
- const char* utf8,
- size_t utf8Bytes,
- SkPoint point,
- SkScalar width,
- RunIteratorQueue& runSegmenter,
- const BiDiRunIterator* bidi,
- const LanguageRunIterator* language,
- const ScriptRunIterator* script,
- const FontRunIterator* font) const
+SkPoint SkShaperHarfBuzz::shapeOk(RunHandler* handler,
+ const char* utf8,
+ size_t utf8Bytes,
+ SkPoint point,
+ SkScalar width,
+ RunIteratorQueue& runSegmenter,
+ const BiDiRunIterator* bidi,
+ const LanguageRunIterator* language,
+ const ScriptRunIterator* script,
+ const FontRunIterator* font) const
{
SkTArray<ShapedRun> runs;
{
@@ -1288,14 +1304,14 @@
}
-ShapedRun SkShaper::Impl::shape(const char* utf8,
- const size_t utf8Bytes,
- const char* utf8Start,
- const char* utf8End,
- const BiDiRunIterator* bidi,
- const LanguageRunIterator* language,
- const ScriptRunIterator* script,
- const FontRunIterator* font) const
+ShapedRun SkShaperHarfBuzz::shape(const char* utf8,
+ const size_t utf8Bytes,
+ const char* utf8Start,
+ const char* utf8End,
+ const BiDiRunIterator* bidi,
+ const LanguageRunIterator* language,
+ const ScriptRunIterator* script,
+ const FontRunIterator* font) const
{
ShapedRun run(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
diff --git a/modules/skshaper/src/SkShaper_primitive.cpp b/modules/skshaper/src/SkShaper_primitive.cpp
index 9295a62..f69fecb 100644
--- a/modules/skshaper/src/SkShaper_primitive.cpp
+++ b/modules/skshaper/src/SkShaper_primitive.cpp
@@ -5,19 +5,30 @@
* found in the LICENSE file.
*/
-#include "SkShaper.h"
#include "SkFontMetrics.h"
+#include "SkMakeUnique.h"
+#include "SkShaper.h"
#include "SkStream.h"
#include "SkTo.h"
#include "SkTypeface.h"
#include "SkUTF.h"
-struct SkShaper::Impl {};
-SkShaper::SkShaper() : fImpl(nullptr) {}
+class SkShaperPrimitive : public SkShaper {
+public:
+ SkShaperPrimitive() {}
+private:
+ SkPoint shape(RunHandler* handler,
+ const SkFont& srcFont,
+ const char* utf8text,
+ size_t textBytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const override;
+};
-SkShaper::~SkShaper() {}
-
-bool SkShaper::good() const { return true; }
+std::unique_ptr<SkShaper> SkShaper::MakePrimitive() {
+ return skstd::make_unique<SkShaperPrimitive>();
+}
static inline bool is_breaking_whitespace(SkUnichar c) {
switch (c) {
@@ -129,13 +140,13 @@
return text - start;
}
-SkPoint SkShaper::shape(RunHandler* handler,
- const SkFont& font,
- const char* utf8text,
- size_t textBytes,
- bool leftToRight,
- SkPoint point,
- SkScalar width) const {
+SkPoint SkShaperPrimitive::shape(RunHandler* handler,
+ const SkFont& font,
+ const char* utf8text,
+ size_t textBytes,
+ bool leftToRight,
+ SkPoint point,
+ SkScalar width) const {
sk_ignore_unused_variable(leftToRight);
int glyphCount = font.countText(utf8text, textBytes, SkTextEncoding::kUTF8);
diff --git a/samplecode/SampleTextBox.cpp b/samplecode/SampleTextBox.cpp
index a0eb5b4..1d37b19 100644
--- a/samplecode/SampleTextBox.cpp
+++ b/samplecode/SampleTextBox.cpp
@@ -25,12 +25,6 @@
#include "SkTypeface.h"
#include "SkUTF.h"
-extern void skia_set_text_gamma(float blackGamma, float whiteGamma);
-
-#if defined(SK_BUILD_FOR_WIN) && defined(SK_FONTHOST_WIN_GDI)
-extern SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);
-#endif
-
static const char gText[] =
"When in the Course of human events it becomes necessary for one people "
"to dissolve the political bands which have connected them with another "
@@ -41,20 +35,7 @@
class TextBoxView : public Sample {
public:
- TextBoxView() {
-#if defined(SK_BUILD_FOR_WIN) && defined(SK_FONTHOST_WIN_GDI)
- LOGFONT lf;
- sk_bzero(&lf, sizeof(lf));
- lf.lfHeight = 9;
- SkTypeface* tf0 = SkCreateTypefaceFromLOGFONT(lf);
- lf.lfHeight = 12;
- SkTypeface* tf1 = SkCreateTypefaceFromLOGFONT(lf);
- // we assert that different sizes should not affect which face we get
- SkASSERT(tf0 == tf1);
- tf0->unref();
- tf1->unref();
-#endif
- }
+ TextBoxView() : fShaper(SkShaper::Make()) {}
protected:
bool onQuery(Sample::Event* evt) override {
@@ -71,8 +52,6 @@
canvas->clipRect(SkRect::MakeWH(w, h));
canvas->drawColor(bg);
- SkShaper shaper;
-
SkScalar margin = 20;
SkPaint paint;
@@ -83,8 +62,8 @@
SkFont font(nullptr, SkIntToScalar(i));
font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
- SkPoint end = shaper.shape(&builder, font, gText, strlen(gText), true,
- { margin, margin }, w - margin);
+ SkPoint end = fShaper->shape(&builder, font, gText, strlen(gText), true,
+ { margin, margin }, w - margin);
canvas->drawTextBlob(builder.makeBlob(), 0, 0, paint);
canvas->translate(0, end.y());
@@ -103,6 +82,7 @@
}
private:
+ std::unique_ptr<SkShaper> fShaper;
typedef Sample INHERITED;
};
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index 303558e..1c7bff1 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -1873,7 +1873,7 @@
SkRect bounds;
lua2rect(L, 2, &bounds);
- SkShaper shaper;
+ std::unique_ptr<SkShaper> shaper = SkShaper::Make();
// TODO: restore this logic based on SkFont instead of SkPaint
#if 0
@@ -1883,8 +1883,8 @@
SkFont font;
#endif
SkTextBlobBuilderRunHandler builder(text);
- SkPoint end = shaper.shape(&builder, font, text, strlen(text), true,
- { bounds.left(), bounds.top() }, bounds.width());
+ SkPoint end = shaper->shape(&builder, font, text, strlen(text), true,
+ { bounds.left(), bounds.top() }, bounds.width());
push_ref<SkTextBlob>(L, builder.makeBlob());
SkLua(L).pushScalar(end.fY);
diff --git a/tools/using_skia_and_harfbuzz.cpp b/tools/using_skia_and_harfbuzz.cpp
index 586b9e8..37bc7b5 100644
--- a/tools/using_skia_and_harfbuzz.cpp
+++ b/tools/using_skia_and_harfbuzz.cpp
@@ -208,12 +208,12 @@
if (font_file.size() > 0) {
typeface = SkTypeface::MakeFromFile(font_file.c_str(), 0 /* index */);
}
- SkShaper shaper;
- assert(shaper.good());
+ std::unique_ptr<SkShaper> shaper = SkShaper::Make();
+ assert(shaper);
//SkString line("This is هذا هو الخط a line.");
//SkString line("This is a line هذا هو الخط.");
for (std::string line; std::getline(std::cin, line);) {
- placement.WriteLine(shaper, line.c_str(), line.size());
+ placement.WriteLine(*shaper, line.c_str(), line.size());
}
doc->close();