21#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
29#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
32#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
35#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
48 RunHandler(
const char* utf8Text,
size_t) : fUtf8Text(utf8Text) {}
49 using RunCallback = void (*)(
void* context,
55 const uint32_t* clusters,
57 void setRunCallback(RunCallback
f,
void* context) {
58 fCallbackContext = context;
59 fCallbackFunction =
f;
63 SkPoint endPoint()
const {
return fOffset; }
64 SkPoint finalPosition()
const {
return fCurrentPosition; }
66 void beginLine()
override;
67 void runInfo(
const RunInfo&)
override;
68 void commitRunInfo()
override;
70 void commitRunBuffer(
const RunInfo&)
override;
71 void commitLine()
override;
73 const std::vector<size_t>& lineEndOffsets()
const {
return fLineEndOffsets; }
76 if (0 == fMaxRunAscent || 0 == fMaxRunDescent) {
78 font.getMetrics(&metrics);
79 return {fCurrentPosition.
x(),
81 fCurrentPosition.
x() +
font.getSize(),
84 return {fCurrentPosition.
x(),
85 fCurrentPosition.
y() + fMaxRunAscent,
86 fCurrentPosition.
x() +
font.getSize(),
87 fCurrentPosition.
y() + fMaxRunDescent};
94 std::vector<size_t> fLineEndOffsets;
95 const SkGlyphID* fCurrentGlyphs =
nullptr;
96 const SkPoint* fCurrentPoints =
nullptr;
97 void* fCallbackContext =
nullptr;
98 RunCallback fCallbackFunction =
nullptr;
99 char const *
const fUtf8Text;
100 size_t fTextOffset = 0;
101 uint32_t* fClusters =
nullptr;
102 int fClusterOffset = 0;
107 SkPoint fCurrentPosition = {0, 0};
113#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
115#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
120#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
125#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
135void RunHandler::beginLine() {
136 fCurrentPosition = fOffset;
144 info.fFont.getMetrics(&metrics);
150void RunHandler::commitRunInfo() {
151 fCurrentPosition.
fY -= fMaxRunAscent;
155 int glyphCount = SkTFitsIn<int>(
info.glyphCount) ?
info.glyphCount : INT_MAX;
156 int utf8RangeSize = SkTFitsIn<int>(
info.utf8Range.size()) ?
info.utf8Range.size() : INT_MAX;
158 const auto& runBuffer = fBuilder.allocRunTextPos(
info.fFont, glyphCount, utf8RangeSize);
159 fCurrentGlyphs = runBuffer.glyphs;
160 fCurrentPoints = runBuffer.points();
162 if (runBuffer.utf8text && fUtf8Text) {
163 memcpy(runBuffer.utf8text, fUtf8Text +
info.utf8Range.begin(), utf8RangeSize);
165 fClusters = runBuffer.clusters;
166 fGlyphCount = glyphCount;
167 fClusterOffset =
info.utf8Range.begin();
169 return {runBuffer.glyphs,
182 if (fCallbackFunction) {
183 fCallbackFunction(fCallbackContext,
185 info.utf8Range.end(),
193 for (
int i = 0;
i < fGlyphCount; ++
i) {
194 SkASSERT(fClusters[
i] >= (
unsigned)fClusterOffset);
195 fClusters[
i] -= fClusterOffset;
197 fCurrentPosition +=
info.fAdvance;
198 fTextOffset =
std::max(fTextOffset,
info.utf8Range.end());
201void RunHandler::commitLine() {
202 if (fLineEndOffsets.empty() || fTextOffset > fLineEndOffsets.back()) {
204 fLineEndOffsets.push_back(fTextOffset);
206 fOffset += { 0, fMaxRunDescent + fMaxRunLeading - fMaxRunAscent };
210 return fBuilder.make();
216 if (fabsf(advance) < 1.0f) {
217 advance = copysignf(1.0f, advance);
226 const char* utf8Text,
227 size_t utf8TextBytes,
231 const uint32_t* clusters,
239 font.getMetrics(&metrics);
240 std::unique_ptr<float[]> advances(
new float[glyphCount]);
241 font.getWidths(
glyphs, glyphCount, advances.get());
244 size_t clusterStart = 0;
245 for (
size_t glyphIndex = 0; glyphIndex < glyphCount; ++glyphIndex) {
246 if (glyphIndex + 1 < glyphCount
247 && clusters[glyphIndex] == clusters[glyphIndex + 1]) {
250 unsigned textBegin = clusters[glyphIndex];
251 unsigned textEnd = utf8TextBytes;
252 for (
size_t i = 0;
i < glyphCount; ++
i) {
253 if (clusters[
i] >= textEnd) {
254 textEnd = clusters[
i] + 1;
257 for (
size_t i = 0;
i < glyphCount; ++
i) {
258 if (clusters[
i] > textBegin && clusters[
i] < textEnd) {
259 textEnd = clusters[
i];
260 if (textEnd == textBegin + 1) {
break; }
263 SkASSERT(glyphIndex + 1 > clusterStart);
264 unsigned clusterGlyphCount = glyphIndex + 1 - clusterStart;
265 const SkPoint* clusterGlyphPositions = &positions[clusterStart];
266 const float* clusterAdvances = &advances[clusterStart];
267 clusterStart = glyphIndex + 1;
270 for (
unsigned i = 1;
i < clusterGlyphCount; ++
i) {
273 if (textBegin + 1 == textEnd) {
274 cursors[textBegin] = clusterBox;
277 int textCount = textEnd - textBegin;
279 if (codePointCount == 1) {
280 cursors[textBegin] = clusterBox;
284 float width = clusterBox.
width() / codePointCount;
286 const char* ptr = utf8Text + textBegin;
287 const char*
end = utf8Text + textEnd;
288 float x = clusterBox.
left();
290 const char* nextPtr = ptr;
292 int firstIndex = ptr - utf8Text;
294 cursors[firstIndex] =
SkRect{
x, clusterBox.
top(), nextX, clusterBox.
bottom()};
313 std::unique_ptr<SkShaper> shaper =
nullptr;
314#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
323 RunHandler runHandler(utf8Text, textByteLen);
325 result.glyphBounds.resize(textByteLen);
327 c =
SkRect{-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX};
331 static constexpr uint8_t kBidiLevelLTR = 0;
332 std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
nullptr;
333#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
335 unicode, utf8Text, textByteLen, kBidiLevelLTR);
338 bidi = std::make_unique<SkShaper::TrivialBiDiRunIterator>(kBidiLevelLTR, textByteLen);
342 std::unique_ptr<SkShaper::LanguageRunIterator> language =
346 std::unique_ptr<SkShaper::ScriptRunIterator>
script =
350 std::unique_ptr<SkShaper::FontRunIterator> fontRuns =
354 shaper->shape(utf8Text,
364 if (runHandler.lineEndOffsets().size() > 1) {
365 result.lineBreakOffsets = runHandler.lineEndOffsets();
367 result.lineBreakOffsets.pop_back();
370 result.blob = runHandler.makeBlob();
372 result.glyphBounds.push_back(runHandler.finalRect(
font));
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
sk_sp< SkUnicode > get_unicode()
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
static std::unique_ptr< ScriptRunIterator > MakeScriptRunIterator(const char *utf8, size_t utf8Bytes, SkFourByteTag script)
static std::unique_ptr< FontRunIterator > MakeFontMgrRunIterator(const char *utf8, size_t utf8Bytes, const SkFont &font, sk_sp< SkFontMgr > fallback)
static std::unique_ptr< LanguageRunIterator > MakeStdLanguageRunIterator(const char *utf8, size_t utf8Bytes)
sk_sp< SkFontMgr > fontMgr
static float max(float r, float g, float b)
static float min(float r, float g, float b)
ShapeResult Shape(const char *ut8text, size_t textByteLen, const SkFont &font, sk_sp< SkFontMgr > fontMgr, const char *locale, float width)
SKSHAPER_API std::unique_ptr< SkShaper > ShaperDrivenWrapper(sk_sp< SkUnicode > unicode, sk_sp< SkFontMgr > fallback)
SKSHAPER_API std::unique_ptr< SkShaper > PrimitiveText()
SKSHAPER_API std::unique_ptr< SkShaper::BiDiRunIterator > BidiRunIterator(sk_sp< SkUnicode > unicode, const char *utf8, size_t utf8Bytes, uint8_t bidiLevel)
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
SK_SPI int CountUTF8(const char *utf8, size_t byteLength)
SKUNICODE_API sk_sp< SkUnicode > Make()
SKUNICODE_API sk_sp< SkUnicode > Make()
SKUNICODE_API sk_sp< SkUnicode > Make()
font
Font Metadata and Metrics.
static SkRect selection_box(const SkFontMetrics &metrics, float advance, SkPoint pos)
static void set_character_bounds(void *context, const char *utf8Text, size_t utf8TextBytes, size_t glyphCount, const SkGlyphID *glyphs, const SkPoint *positions, const uint32_t *clusters, const SkFont &font)
SkScalar fLeading
distance to add between lines, typically positive or zero
SkScalar fAscent
distance to reserve above baseline, typically negative
SkScalar fDescent
distance to reserve below baseline, typically positive
constexpr float y() const
constexpr float x() const
constexpr float left() const
constexpr float top() const
constexpr float width() const
void join(const SkRect &r)
constexpr float bottom() const
std::vector< bool > GetUtf8WordBoundaries(const char *begin, size_t byteCount, const char *locale)