Hack up SkShaper to pass additional callback info
- rename LineHandler -> RunHandler (since it gets called per run)
- pass additionl run info:
* line index
* cumulative advance
* ascent/descent/leading
Bug: skia:
Change-Id: Ie848e5a35243088b99989c73fdec44c6a1bdd051
Reviewed-on: https://skia-review.googlesource.com/c/183300
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/skshaper/include/SkShaper.h b/modules/skshaper/include/SkShaper.h
index 391e583..aa37d5c 100644
--- a/modules/skshaper/include/SkShaper.h
+++ b/modules/skshaper/include/SkShaper.h
@@ -27,9 +27,17 @@
SkShaper(sk_sp<SkTypeface> face);
~SkShaper();
- class LineHandler {
+ class RunHandler {
public:
- virtual ~LineHandler() = default;
+ virtual ~RunHandler() = default;
+
+ struct RunInfo {
+ size_t fLineIndex;
+ SkVector fAdvance;
+ SkScalar fAscent,
+ fDescent,
+ fLeading;
+ };
struct Buffer {
SkGlyphID* glyphs; // required
@@ -38,11 +46,12 @@
uint32_t* clusters; // optional
};
- virtual Buffer newLineBuffer(const SkFont&, int glyphCount, int utf8textCount) = 0;
+ virtual Buffer newRunBuffer(const RunInfo&, const SkFont&, int glyphCount,
+ int utf8textCount) = 0;
};
bool good() const;
- SkPoint shape(LineHandler* handler,
+ SkPoint shape(RunHandler* handler,
const SkFont& srcPaint,
const char* utf8text,
size_t textBytes,
@@ -61,11 +70,11 @@
/**
* Helper for shaping text directly into a SkTextBlob.
*/
-class SkTextBlobBuilderLineHandler final : public SkShaper::LineHandler {
+class SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler {
public:
sk_sp<SkTextBlob> makeBlob();
- SkShaper::LineHandler::Buffer newLineBuffer(const SkFont&, int, int) override;
+ SkShaper::RunHandler::Buffer newRunBuffer(const RunInfo&, const SkFont&, int, int) override;
private:
SkTextBlobBuilder fBuilder;
diff --git a/modules/skshaper/src/SkShaper.cpp b/modules/skshaper/src/SkShaper.cpp
index 78f973c..e08b7b3 100644
--- a/modules/skshaper/src/SkShaper.cpp
+++ b/modules/skshaper/src/SkShaper.cpp
@@ -9,9 +9,10 @@
#include "SkTextBlobPriv.h"
-SkShaper::LineHandler::Buffer SkTextBlobBuilderLineHandler::newLineBuffer(const SkFont& font,
- int glyphCount,
- int textCount) {
+SkShaper::RunHandler::Buffer SkTextBlobBuilderRunHandler::newRunBuffer(const RunInfo&,
+ const SkFont& font,
+ int glyphCount,
+ int textCount) {
const auto& runBuffer = SkTextBlobBuilderPriv::AllocRunTextPos(&fBuilder, font, glyphCount,
textCount, SkString());
return { runBuffer.glyphs,
@@ -20,6 +21,6 @@
runBuffer.clusters };
}
-sk_sp<SkTextBlob> SkTextBlobBuilderLineHandler::makeBlob() {
+sk_sp<SkTextBlob> SkTextBlobBuilderRunHandler::makeBlob() {
return fBuilder.make();
}
diff --git a/modules/skshaper/src/SkShaper_harfbuzz.cpp b/modules/skshaper/src/SkShaper_harfbuzz.cpp
index beb5923..6560a6c 100644
--- a/modules/skshaper/src/SkShaper_harfbuzz.cpp
+++ b/modules/skshaper/src/SkShaper_harfbuzz.cpp
@@ -407,17 +407,19 @@
SkFont fFont;
UBiDiLevel fLevel;
std::unique_ptr<ShapedGlyph[]> fGlyphs;
+ SkVector fAdvance = { 0, 0 };
};
static constexpr bool is_LTR(UBiDiLevel level) {
return (level & 1) == 0;
}
-static void append(SkShaper::LineHandler* handler, const ShapedRun& run, int start, int end,
+static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
+ const ShapedRun& run, int start, int end,
SkPoint* p) {
unsigned len = end - start;
- const auto buffer = handler->newLineBuffer(run.fFont, len, run.fUtf8End - run.fUtf8Start);
+ const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8End - run.fUtf8Start);
SkASSERT(buffer.glyphs);
SkASSERT(buffer.positions);
@@ -522,7 +524,7 @@
fImpl->fBreakIterator;
}
-SkPoint SkShaper::shape(LineHandler* handler,
+SkPoint SkShaper::shape(RunHandler* handler,
const SkFont& srcPaint,
const char* utf8,
size_t utf8Bytes,
@@ -647,6 +649,7 @@
hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
double textSizeY = run.fFont.getSize() / scaleY;
double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
+ SkVector runAdvance = { 0, 0 };
for (unsigned i = 0; i < len; i++) {
ShapedGlyph& glyph = run.fGlyphs[i];
glyph.fID = info[i].codepoint;
@@ -658,7 +661,10 @@
glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
//info->mask safe_to_break;
glyph.fMustLineBreakBefore = false;
+
+ runAdvance += glyph.fAdvance;
}
+ run.fAdvance = runAdvance;
int32_t clusterOffset = utf8Start - utf8;
uint32_t previousCluster = 0xFFFFFFFF;
@@ -729,6 +735,7 @@
SkScalar maxDescent = 0;
SkScalar maxLeading = 0;
int previousRunIndex = -1;
+ size_t lineIndex = 0;
while (glyphIterator.current()) {
int runIndex = glyphIterator.fRunIndex;
int glyphIndex = glyphIterator.fGlyphIndex;
@@ -767,7 +774,16 @@
int endGlyphIndex = (logicalIndex == runIndex)
? glyphIndex + 1
: runs[logicalIndex].fNumGlyphs;
- append(handler, runs[logicalIndex], startGlyphIndex, endGlyphIndex, ¤tPoint);
+
+ const auto& run = runs[logicalIndex];
+ const RunHandler::RunInfo info = {
+ lineIndex,
+ run.fAdvance,
+ maxAscent,
+ maxDescent,
+ maxLeading,
+ };
+ append(handler, info, run, startGlyphIndex, endGlyphIndex, ¤tPoint);
}
currentPoint.fY += maxDescent + maxLeading;
@@ -776,6 +792,7 @@
maxDescent = 0;
maxLeading = 0;
previousRunIndex = -1;
+ ++lineIndex;
previousBreak = glyphIterator;
}
}
diff --git a/modules/skshaper/src/SkShaper_primitive.cpp b/modules/skshaper/src/SkShaper_primitive.cpp
index 3d54262..f00db9f 100644
--- a/modules/skshaper/src/SkShaper_primitive.cpp
+++ b/modules/skshaper/src/SkShaper_primitive.cpp
@@ -31,7 +31,7 @@
return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
}
-SkPoint SkShaper::shape(LineHandler* handler,
+SkPoint SkShaper::shape(RunHandler* handler,
const SkFont& srcFont,
const char* utf8text,
size_t textBytes,
@@ -52,7 +52,14 @@
font.getMetrics(&metrics);
point.fY -= metrics.fAscent;
- const auto buffer = handler->newLineBuffer(font, glyphCount, textBytes);
+ const RunHandler::RunInfo info = {
+ 0,
+ { font.measureText(utf8text, textBytes, SkTextEncoding::kUTF8), 0 },
+ metrics.fAscent,
+ metrics.fDescent,
+ metrics.fLeading,
+ };
+ const auto buffer = handler->newRunBuffer(info, font, glyphCount, textBytes);
SkAssertResult(font.textToGlyphs(utf8text, textBytes, SkTextEncoding::kUTF8, buffer.glyphs,
glyphCount) == glyphCount);
font.getPos(buffer.glyphs, glyphCount, buffer.positions, point);