2016-07-11 21:30:39 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2019-07-26 18:54:40 +00:00
|
|
|
#include "include/core/SkFontMgr.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#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"
|
2019-04-03 21:53:53 +00:00
|
|
|
|
|
|
|
#include <memory>
|
2016-07-11 21:30:39 +00:00
|
|
|
|
2018-11-26 22:23:24 +00:00
|
|
|
class SkFont;
|
2019-04-03 21:53:53 +00:00
|
|
|
class SkFontMgr;
|
2016-07-11 21:30:39 +00:00
|
|
|
|
|
|
|
/**
|
2016-08-03 17:43:55 +00:00
|
|
|
Shapes text using HarfBuzz and places the shaped text into a
|
2018-12-12 15:54:49 +00:00
|
|
|
client-managed buffer.
|
2016-08-03 17:43:55 +00:00
|
|
|
|
|
|
|
If compiled without HarfBuzz, fall back on SkPaint::textToGlyphs.
|
2016-07-11 21:30:39 +00:00
|
|
|
*/
|
|
|
|
class SkShaper {
|
|
|
|
public:
|
2019-02-15 19:46:18 +00:00
|
|
|
static std::unique_ptr<SkShaper> MakePrimitive();
|
|
|
|
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
|
2019-07-26 18:54:40 +00:00
|
|
|
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);
|
2019-02-15 19:46:18 +00:00
|
|
|
#endif
|
|
|
|
|
2019-07-26 18:54:40 +00:00
|
|
|
static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr);
|
2019-02-15 19:46:18 +00:00
|
|
|
|
2019-02-14 20:32:44 +00:00
|
|
|
SkShaper();
|
2019-02-15 19:46:18 +00:00
|
|
|
virtual ~SkShaper();
|
2016-07-11 21:30:39 +00:00
|
|
|
|
2019-03-27 19:37:13 +00:00
|
|
|
class RunIterator {
|
|
|
|
public:
|
|
|
|
virtual ~RunIterator() = default;
|
|
|
|
/** Set state to that of current run and move iterator to end of that run. */
|
|
|
|
virtual void consume() = 0;
|
|
|
|
/** Offset to one past the last (utf8) element in the current run. */
|
|
|
|
virtual size_t endOfCurrentRun() const = 0;
|
|
|
|
/** Return true if consume should no longer be called. */
|
|
|
|
virtual bool atEnd() const = 0;
|
|
|
|
};
|
2019-04-03 21:53:53 +00:00
|
|
|
|
2019-05-29 22:54:26 +00:00
|
|
|
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:
|
2019-04-03 21:53:53 +00:00
|
|
|
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);
|
2019-05-29 22:54:26 +00:00
|
|
|
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;
|
|
|
|
};
|
2019-04-03 21:53:53 +00:00
|
|
|
|
2019-03-27 19:37:13 +00:00
|
|
|
class BiDiRunIterator : public RunIterator {
|
|
|
|
public:
|
|
|
|
/** The unicode bidi embedding level (even ltr, odd rtl) */
|
|
|
|
virtual uint8_t currentLevel() const = 0;
|
|
|
|
};
|
2019-04-03 21:53:53 +00:00
|
|
|
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
|
2019-05-29 22:54:26 +00:00
|
|
|
static std::unique_ptr<BiDiRunIterator>
|
2019-04-03 21:53:53 +00:00
|
|
|
MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
|
|
|
|
#endif
|
2019-05-29 22:54:26 +00:00
|
|
|
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;
|
|
|
|
};
|
2019-04-03 21:53:53 +00:00
|
|
|
|
2019-03-27 19:37:13 +00:00
|
|
|
class ScriptRunIterator : public RunIterator {
|
|
|
|
public:
|
|
|
|
/** Should be iso15924 codes. */
|
|
|
|
virtual SkFourByteTag currentScript() const = 0;
|
|
|
|
};
|
2019-04-03 21:53:53 +00:00
|
|
|
#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
|
2019-05-29 22:54:26 +00:00
|
|
|
static std::unique_ptr<ScriptRunIterator>
|
2019-04-03 21:53:53 +00:00
|
|
|
MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes);
|
|
|
|
#endif
|
2019-05-29 22:54:26 +00:00
|
|
|
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;
|
|
|
|
};
|
2019-04-03 21:53:53 +00:00
|
|
|
|
2019-03-27 19:37:13 +00:00
|
|
|
class LanguageRunIterator : public RunIterator {
|
|
|
|
public:
|
|
|
|
/** Should be BCP-47, c locale names may also work. */
|
|
|
|
virtual const char* currentLanguage() const = 0;
|
|
|
|
};
|
2019-05-29 22:54:26 +00:00
|
|
|
static std::unique_ptr<LanguageRunIterator>
|
2019-04-03 21:53:53 +00:00
|
|
|
MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes);
|
2019-05-29 22:54:26 +00:00
|
|
|
class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> {
|
|
|
|
public:
|
|
|
|
TrivialLanguageRunIterator(const char* language, size_t utf8Bytes)
|
|
|
|
: TrivialRunIterator(utf8Bytes), fLanguage(language) {}
|
2019-05-30 18:09:33 +00:00
|
|
|
const char* currentLanguage() const override { return fLanguage.c_str(); }
|
2019-05-29 22:54:26 +00:00
|
|
|
private:
|
2019-05-30 18:09:33 +00:00
|
|
|
SkString fLanguage;
|
2019-05-29 22:54:26 +00:00
|
|
|
};
|
2019-03-27 19:37:13 +00:00
|
|
|
|
2019-01-11 16:08:35 +00:00
|
|
|
class RunHandler {
|
2018-12-12 15:54:49 +00:00
|
|
|
public:
|
2019-01-11 16:08:35 +00:00
|
|
|
virtual ~RunHandler() = default;
|
|
|
|
|
2019-03-25 19:38:22 +00:00
|
|
|
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; }
|
|
|
|
};
|
|
|
|
|
2019-04-01 23:01:09 +00:00
|
|
|
struct RunInfo {
|
|
|
|
const SkFont& fFont;
|
|
|
|
uint8_t fBidiLevel;
|
|
|
|
SkVector fAdvance;
|
|
|
|
size_t glyphCount;
|
|
|
|
Range utf8Range;
|
|
|
|
};
|
2019-02-07 15:56:55 +00:00
|
|
|
|
2019-04-01 23:01:09 +00:00
|
|
|
struct Buffer {
|
|
|
|
SkGlyphID* glyphs; // required
|
2019-05-30 22:34:05 +00:00
|
|
|
SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i]
|
|
|
|
// if ( offsets) positions[i+1]-positions[i] are advances
|
|
|
|
SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i]
|
|
|
|
uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i]
|
|
|
|
SkPoint point; // offset to add to all positions
|
2019-04-01 23:01:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Called when beginning a line. */
|
|
|
|
virtual void beginLine() = 0;
|
|
|
|
|
|
|
|
/** Called once for each run in a line. Can compute baselines and offsets. */
|
|
|
|
virtual void runInfo(const RunInfo&) = 0;
|
|
|
|
|
|
|
|
/** Called after all runInfo calls for a line. */
|
|
|
|
virtual void commitRunInfo() = 0;
|
|
|
|
|
|
|
|
/** Called for each run in a line after commitRunInfo. The buffer will be filled out. */
|
|
|
|
virtual Buffer runBuffer(const RunInfo&) = 0;
|
|
|
|
|
|
|
|
/** Called after each runBuffer is filled out. */
|
|
|
|
virtual void commitRunBuffer(const RunInfo&) = 0;
|
|
|
|
|
|
|
|
/** Called when ending a line. */
|
2019-02-07 15:56:55 +00:00
|
|
|
virtual void commitLine() = 0;
|
2018-12-12 15:54:49 +00:00
|
|
|
};
|
|
|
|
|
2019-04-01 23:01:09 +00:00
|
|
|
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;
|
2019-03-27 19:37:13 +00:00
|
|
|
|
2016-07-11 21:30:39 +00:00
|
|
|
private:
|
|
|
|
SkShaper(const SkShaper&) = delete;
|
|
|
|
SkShaper& operator=(const SkShaper&) = delete;
|
|
|
|
};
|
|
|
|
|
2018-12-12 15:54:49 +00:00
|
|
|
/**
|
|
|
|
* Helper for shaping text directly into a SkTextBlob.
|
|
|
|
*/
|
2019-01-11 16:08:35 +00:00
|
|
|
class SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler {
|
2018-12-12 15:54:49 +00:00
|
|
|
public:
|
2019-04-01 23:01:09 +00:00
|
|
|
SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset)
|
|
|
|
: fUtf8Text(utf8Text)
|
|
|
|
, fOffset(offset) {}
|
2018-12-12 15:54:49 +00:00
|
|
|
sk_sp<SkTextBlob> makeBlob();
|
2019-04-01 23:01:09 +00:00
|
|
|
SkPoint endPoint() { return fOffset; }
|
2018-12-12 15:54:49 +00:00
|
|
|
|
2019-04-01 23:01:09 +00:00
|
|
|
void beginLine() override;
|
|
|
|
void runInfo(const RunInfo&) override;
|
|
|
|
void commitRunInfo() override;
|
|
|
|
Buffer runBuffer(const RunInfo&) override;
|
|
|
|
void commitRunBuffer(const RunInfo&) override;
|
|
|
|
void commitLine() override;
|
2019-02-07 15:56:55 +00:00
|
|
|
|
2018-12-12 15:54:49 +00:00
|
|
|
private:
|
|
|
|
SkTextBlobBuilder fBuilder;
|
2019-02-08 22:46:38 +00:00
|
|
|
char const * const fUtf8Text;
|
|
|
|
uint32_t* fClusters;
|
|
|
|
int fClusterOffset;
|
|
|
|
int fGlyphCount;
|
2019-04-01 23:01:09 +00:00
|
|
|
SkScalar fMaxRunAscent;
|
|
|
|
SkScalar fMaxRunDescent;
|
|
|
|
SkScalar fMaxRunLeading;
|
|
|
|
SkPoint fCurrentPosition;
|
|
|
|
SkPoint fOffset;
|
2018-12-12 15:54:49 +00:00
|
|
|
};
|
|
|
|
|
2016-07-11 21:30:39 +00:00
|
|
|
#endif // SkShaper_DEFINED
|