more simple makers for textblobs
To aid in the transition away from drawText, drawPosText, etc.
... see https://skia-review.googlesource.com/c/skia/+/175240
Definitely need to have a follow-on discussion about tradeoffs for the
various positioning backends.
Bug: skia:
Change-Id: I236e151f6604d868dc18f98503c371f41593ec6e
Reviewed-on: https://skia-review.googlesource.com/c/175248
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h
index 1e07e1a..934791e 100644
--- a/include/core/SkTextBlob.h
+++ b/include/core/SkTextBlob.h
@@ -80,6 +80,39 @@
return MakeFromText(string, strlen(string), font, encoding);
}
+ /** Experimental.
+ Returns a textblob built from a single run of text with x-positions and a single y value.
+ This is equivalent to using SkTextBlobBuilder and calling allocRunPosH().
+ Returns nullptr if byteLength is zero.
+
+ @param text character code points or glyphs drawn (based on encoding)
+ @param byteLength byte length of text array
+ @param xpos array of x-positions, must contain values for all of the character points.
+ @param constY shared y-position for each character point, to be paired with each xpos.
+ @param font SkFont used for this run
+ @param encoding specifies the encoding of the text array.
+ @return new textblob or nullptr
+ */
+ static sk_sp<SkTextBlob> MakeFromPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY, const SkFont& font,
+ SkTextEncoding encoding = kUTF8_SkTextEncoding);
+
+ /** Experimental.
+ Returns a textblob built from a single run of text with positions.
+ This is equivalent to using SkTextBlobBuilder and calling allocRunPos().
+ Returns nullptr if byteLength is zero.
+
+ @param text character code points or glyphs drawn (based on encoding)
+ @param byteLength byte length of text array
+ @param pos array of positions, must contain values for all of the character points.
+ @param font SkFont used for this run
+ @param encoding specifies the encoding of the text array.
+ @return new textblob or nullptr
+ */
+ static sk_sp<SkTextBlob> MakeFromPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkFont& font,
+ SkTextEncoding encoding = kUTF8_SkTextEncoding);
+
/** Writes data to allow later reconstruction of SkTextBlob. memory points to storage
to receive the encoded data, and memory_size describes the size of storage.
Returns bytes used if provided storage is large enough to hold all data;
diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp
index 1b0a86b..8f3fd9c 100644
--- a/src/core/SkFont.cpp
+++ b/src/core/SkFont.cpp
@@ -150,22 +150,7 @@
SkASSERT(text);
- int count = 0; // fix uninitialized warning (even though the switch is complete!)
-
- switch (encoding) {
- case kUTF8_SkTextEncoding:
- count = SkUTF::CountUTF8((const char*)text, byteLength);
- break;
- case kUTF16_SkTextEncoding:
- count = SkUTF::CountUTF16((const uint16_t*)text, byteLength);
- break;
- case kUTF32_SkTextEncoding:
- count = SkToInt(byteLength >> 2);
- break;
- case kGlyphID_SkTextEncoding:
- count = SkToInt(byteLength >> 1);
- break;
- }
+ int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
if (!glyphs || count > maxGlyphCount) {
return count;
}
@@ -542,3 +527,18 @@
return bounds;
}
+int SkFontPriv::CountTextElements(const void* text, size_t byteLength, SkTextEncoding encoding) {
+ switch (encoding) {
+ case kUTF8_SkTextEncoding:
+ return SkUTF::CountUTF8(reinterpret_cast<const char*>(text), byteLength);
+ case kUTF16_SkTextEncoding:
+ return SkUTF::CountUTF16(reinterpret_cast<const uint16_t*>(text), byteLength);
+ case kUTF32_SkTextEncoding:
+ return byteLength >> 2;
+ case kGlyphID_SkTextEncoding:
+ return byteLength >> 1;
+ }
+ SkASSERT(false);
+ return 0;
+}
+
diff --git a/src/core/SkFontPriv.h b/src/core/SkFontPriv.h
index 1d1cfc1..a0bbec3 100644
--- a/src/core/SkFontPriv.h
+++ b/src/core/SkFontPriv.h
@@ -58,6 +58,9 @@
@return union of bounds of all glyphs
*/
static SkRect GetFontBounds(const SkFont&);
+
+ // Returns the number of elements (characters or glyphs) in the array.
+ static int CountTextElements(const void* text, size_t byteLength, SkTextEncoding);
};
class SkAutoToGlyphs {
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 2e6b427..6d1adbf 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -718,24 +718,36 @@
sk_sp<SkTextBlob> SkTextBlob::MakeFromText(const void* text, size_t byteLength, const SkFont& font,
SkTextEncoding encoding) {
- SkPaint legacyPaint;
- font.LEGACY_applyToPaint(&legacyPaint);
- legacyPaint.setTextEncoding(encoding);
+ // Note: we deliberately promote this to fully positioned blobs, since we'd have to pay the
+ // same cost down stream (i.e. computing bounds), so its cheaper to pay the cost once now.
+ const int count = font.countText(text, byteLength, encoding);
+ SkTextBlobBuilder builder;
+ auto buffer = builder.allocRunPos(font, count);
+ font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
+ font.getPos(buffer.glyphs, count, reinterpret_cast<SkPoint*>(buffer.pos), {0, 0});
+ return builder.make();
+}
- SkGlyphRunBuilder runBuilder;
+sk_sp<SkTextBlob> SkTextBlob::MakeFromPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkFont& font,
+ SkTextEncoding encoding) {
+ const int count = font.countText(text, byteLength, encoding);
+ SkTextBlobBuilder builder;
+ auto buffer = builder.allocRunPos(font, count);
+ font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
+ memcpy(buffer.pos, pos, count * sizeof(SkPoint));
+ return builder.make();
+}
- runBuilder.drawText(legacyPaint, text, byteLength, SkPoint::Make(0, 0));
-
- auto glyphRunList = runBuilder.useGlyphRunList();
- SkTextBlobBuilder blobBuilder;
- if (!glyphRunList.empty()) {
- auto run = glyphRunList[0];
-
- auto runData = blobBuilder.allocRunPos(font, run.runSize());
- run.filloutGlyphsAndPositions(runData.glyphs, (SkPoint *)runData.pos);
- }
-
- return blobBuilder.make();
+sk_sp<SkTextBlob> SkTextBlob::MakeFromPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkFont& font, SkTextEncoding encoding) {
+ const int count = font.countText(text, byteLength, encoding);
+ SkTextBlobBuilder builder;
+ auto buffer = builder.allocRunPosH(font, count, constY);
+ font.textToGlyphs(text, byteLength, encoding, buffer.glyphs, count);
+ memcpy(buffer.pos, xpos, count * sizeof(SkScalar));
+ return builder.make();
}
sk_sp<SkData> SkTextBlob::serialize(const SkSerialProcs& procs) const {