Add trivial implemenations of shaper run iterators.

Change-Id: I71f9cf2971cdb44ae2d189e29afc2ab330750dcb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/216780
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2019-05-29 18:54:26 -04:00 committed by Skia Commit-Bot
parent cf01a5ccd9
commit e8db325168
4 changed files with 86 additions and 11 deletions

View File

@ -50,6 +50,21 @@ public:
virtual bool atEnd() const = 0;
};
private:
template <typename RunIteratorSubclass>
class TrivialRunIterator : public RunIteratorSubclass {
public:
static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, "");
TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(false) {}
void consume() override { fAtEnd = true; }
size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; }
bool atEnd() const override { return fAtEnd; }
private:
size_t fEnd;
bool fAtEnd;
};
public:
class FontRunIterator : public RunIterator {
public:
virtual const SkFont& currentFont() const = 0;
@ -57,6 +72,14 @@ public:
static std::unique_ptr<FontRunIterator>
MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes,
const SkFont& font, sk_sp<SkFontMgr> fallback);
class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> {
public:
TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes)
: TrivialRunIterator(utf8Bytes), fFont(font) {}
const SkFont& currentFont() const override { return fFont; }
private:
SkFont fFont;
};
class BiDiRunIterator : public RunIterator {
public:
@ -64,9 +87,17 @@ public:
virtual uint8_t currentLevel() const = 0;
};
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
static std::unique_ptr<SkShaper::BiDiRunIterator>
static std::unique_ptr<BiDiRunIterator>
MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
#endif
class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> {
public:
TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes)
: TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {}
uint8_t currentLevel() const override { return fBidiLevel; }
private:
uint8_t fBidiLevel;
};
class ScriptRunIterator : public RunIterator {
public:
@ -74,17 +105,33 @@ public:
virtual SkFourByteTag currentScript() const = 0;
};
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
static std::unique_ptr<SkShaper::ScriptRunIterator>
static std::unique_ptr<ScriptRunIterator>
MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes);
#endif
class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> {
public:
TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes)
: TrivialRunIterator(utf8Bytes), fScript(script) {}
SkFourByteTag currentScript() const override { return fScript; }
private:
SkFourByteTag fScript;
};
class LanguageRunIterator : public RunIterator {
public:
/** Should be BCP-47, c locale names may also work. */
virtual const char* currentLanguage() const = 0;
};
static std::unique_ptr<SkShaper::LanguageRunIterator>
static std::unique_ptr<LanguageRunIterator>
MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes);
class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> {
public:
TrivialLanguageRunIterator(const char* language, size_t utf8Bytes)
: TrivialRunIterator(utf8Bytes), fLanguage(language) {}
const char* currentLanguage() const override { return fLanguage; }
private:
const char* fLanguage;
};
class RunHandler {
public:

View File

@ -272,6 +272,7 @@ hb_blob_t* skhb_get_table(hb_face_t* face, hb_tag_t tag, void* user_data) {
}
HBFont create_hb_font(const SkFont& font) {
SkASSERT(font.getTypeface());
int index;
std::unique_ptr<SkStreamAsset> typefaceAsset = font.getTypeface()->openStream(&index);
HBFace face;

View File

@ -118,7 +118,7 @@ void SkShaperPrimitive::shape(const char* utf8, size_t utf8Bytes,
FontRunIterator& font,
BiDiRunIterator& bidi,
ScriptRunIterator&,
LanguageRunIterator& ,
LanguageRunIterator&,
SkScalar width,
RunHandler* handler) const
{
@ -134,6 +134,7 @@ void SkShaperPrimitive::shape(const char* utf8, size_t utf8Bytes,
SkScalar width,
RunHandler* handler) const {
sk_ignore_unused_variable(leftToRight);
SkASSERT(font.getTypeface());
int glyphCount = font.countText(utf8, utf8Bytes, SkTextEncoding::kUTF8);
if (glyphCount <= 0) {

View File

@ -5,9 +5,19 @@
#if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_BUILD_FOR_GOOGLE3)
#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTo.h"
#include "modules/skshaper/include/SkShaper.h"
#include "tools/Resources.h"
#include <cstdint>
#include <memory>
namespace {
struct RunHandler final : public SkShaper::RunHandler {
const char* fResource;
@ -52,14 +62,30 @@ struct RunHandler final : public SkShaper::RunHandler {
} // namespace
static void cluster_test(skiatest::Reporter* reporter, const char* resource) {
constexpr float kWidth = 400;
if (auto shaper = SkShaper::Make()) {
if (auto data = GetResourceAsData(resource)) {
SkFont font;
RunHandler rh(resource, reporter);
shaper->shape((const char*)data->data(), data->size(), font, true, kWidth, &rh);
}
auto shaper = SkShaper::Make();
if (!shaper) {
ERRORF(reporter, "Could not create shaper.");
return;
}
auto data = GetResourceAsData(resource);
if (!data) {
ERRORF(reporter, "Could not get resource %s.", resource);
return;
}
constexpr float kWidth = 400;
SkFont font(SkTypeface::MakeDefault());
RunHandler rh(resource, reporter);
shaper->shape((const char*)data->data(), data->size(), font, true, kWidth, &rh);
constexpr SkFourByteTag latn = SkSetFourByteTag('l','a','t','n');
auto fontIterator = SkShaper::TrivialFontRunIterator(font, data->size());
auto bidiIterator = SkShaper::TrivialBiDiRunIterator(0, data->size());
auto scriptIterator = SkShaper::TrivialScriptRunIterator(latn, data->size());
auto languageIterator = SkShaper::TrivialLanguageRunIterator("en-US", data->size());
shaper->shape((const char*)data->data(), data->size(),
fontIterator, bidiIterator, scriptIterator, languageIterator, kWidth, &rh);
}
#define SHAPER_TEST(X) DEF_TEST(Shaper_cluster_ ## X, r) { cluster_test(r, "text/" #X ".txt"); }