* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkShaper_DEFINED
#define SkShaper_DEFINED
#include "include/core/SkFontMgr.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypes.h"
#include <memory>
class SkFont;
class SkFontMgr;
Shapes text using HarfBuzz and places the shaped text into a
client-managed buffer.
If compiled without HarfBuzz, fall back on SkPaint::textToGlyphs.
*/
class SkShaper {
public:
static std::unique_ptr<SkShaper> MakePrimitive();
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr);
static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr);
static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr);
#endif
static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr);
SkShaper();
virtual ~SkShaper();
class RunIterator {
public:
virtual ~RunIterator() = default;
virtual void consume() = 0;
virtual size_t endOfCurrentRun() const = 0;
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;
};
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:
virtual uint8_t currentLevel() const = 0;
};
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
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:
virtual SkFourByteTag currentScript() const = 0;
};
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
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:
virtual const char* currentLanguage() const = 0;
};
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.c_str(); }
private:
SkString fLanguage;
};
class RunHandler {
public:
virtual ~RunHandler() = default;
struct Range {
constexpr Range() : fBegin(0), fSize(0) {}
constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {}
size_t fBegin;
size_t fSize;
constexpr size_t begin() const { return fBegin; }
constexpr size_t end() const { return begin() + size(); }
constexpr size_t size() const { return fSize; }
};
struct RunInfo {
const SkFont& fFont;
uint8_t fBidiLevel;
SkVector fAdvance;
size_t glyphCount;
Range utf8Range;
};
struct Buffer {
SkGlyphID* glyphs;
SkPoint* positions;
SkPoint* offsets;
uint32_t* clusters;
SkPoint point;
};
virtual void beginLine() = 0;
virtual void runInfo(const RunInfo&) = 0;
virtual void commitRunInfo() = 0;
virtual Buffer runBuffer(const RunInfo&) = 0;
virtual void commitRunBuffer(const RunInfo&) = 0;
virtual void commitLine() = 0;
};
virtual void shape(const char* utf8, size_t utf8Bytes,
const SkFont& srcFont,
bool leftToRight,
SkScalar width,
RunHandler*) const = 0;
virtual void shape(const char* utf8, size_t utf8Bytes,
FontRunIterator&,
BiDiRunIterator&,
ScriptRunIterator&,
LanguageRunIterator&,
SkScalar width,
RunHandler*) const = 0;
private:
SkShaper(const SkShaper&) = delete;
SkShaper& operator=(const SkShaper&) = delete;
};
* Helper for shaping text directly into a SkTextBlob.
*/
class SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler {
public:
SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset)
: fUtf8Text(utf8Text)
, fOffset(offset) {}
sk_sp<SkTextBlob> makeBlob();
SkPoint endPoint() { return fOffset; }
void beginLine() override;
void runInfo(const RunInfo&) override;
void commitRunInfo() override;
Buffer runBuffer(const RunInfo&) override;
void commitRunBuffer(const RunInfo&) override;
void commitLine() override;
private:
SkTextBlobBuilder fBuilder;
char const * const fUtf8Text;
uint32_t* fClusters;
int fClusterOffset;
int fGlyphCount;
SkScalar fMaxRunAscent;
SkScalar fMaxRunDescent;
SkScalar fMaxRunLeading;
SkPoint fCurrentPosition;
SkPoint fOffset;
};
#endif