breakText on font

Bug: skia:
Change-Id: Iebf65b158a0b08ed8e65b77d9d0aeef8c159d5db
Reviewed-on: https://skia-review.googlesource.com/c/173770
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2018-12-02 22:21:14 -05:00 committed by Skia Commit-Bot
parent 94cca60bfa
commit da1b99f7f5
3 changed files with 69 additions and 3 deletions

View File

@ -295,6 +295,9 @@ public:
*/
bool containsText(const void* text, size_t byteLength, SkTextEncoding encoding) const;
size_t breakText(const void* text, size_t length, SkTextEncoding, SkScalar maxWidth,
SkScalar* measuredWidth = nullptr) const;
/** Returns the advance width of text.
The advance is the normal distance to move before drawing additional text.
Returns the bounding box of text if bounds is not nullptr.

View File

@ -231,6 +231,55 @@ bool SkFont::containsText(const void* textData, size_t byteLength, SkTextEncodin
return true;
}
size_t SkFont::breakText(const void* textD, size_t length, SkTextEncoding encoding,
SkScalar maxWidth, SkScalar* measuredWidth) const {
if (0 == length || !(maxWidth > 0)) {
if (measuredWidth) {
*measuredWidth = 0;
}
return 0;
}
if (0 == fSize) {
if (measuredWidth) {
*measuredWidth = 0;
}
return length;
}
SkCanonicalizeFont canon(*this);
const SkFont& font = canon.getFont();
SkScalar scale = canon.getScale();
auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font);
const char* text = static_cast<const char*>(textD);
const char* stop = text + length;
auto glyphCacheProc = SkFontPriv::GetGlyphCacheProc(encoding, false);
if (scale) {
maxWidth /= scale;
}
SkScalar width = 0;
while (text < stop) {
const char* curr = text;
SkScalar x = glyphCacheProc(cache.get(), &text, stop).fAdvanceX;
if ((width += x) > maxWidth) {
width -= x;
text = curr;
break;
}
}
if (measuredWidth) {
if (scale) {
width *= scale;
}
*measuredWidth = width;
}
return text - stop + length;
}
static void set_bounds(const SkGlyph& g, SkRect* bounds) {
bounds->set(SkIntToScalar(g.fLeft),
SkIntToScalar(g.fTop),

View File

@ -6,9 +6,23 @@
*/
#include "SkAutoMalloc.h"
#include "SkFont.h"
#include "SkPaint.h"
#include "Test.h"
static size_t break_text(const SkPaint& paint, const void* text, size_t length, SkScalar maxw,
SkScalar* measuredw, skiatest::Reporter* reporter) {
size_t n = paint.breakText(text, length, maxw, measuredw);
SkScalar measuredw2;
size_t n2 = SkFont::LEGACY_ExtractFromPaint(paint).breakText(text, length,
(SkTextEncoding)paint.getTextEncoding(), maxw, &measuredw2);
REPORTER_ASSERT(reporter, n == n2);
if (measuredw) {
REPORTER_ASSERT(reporter, *measuredw == measuredw2);
}
return n;
}
static void test_monotonic(skiatest::Reporter* reporter,
const SkPaint& paint,
const char* msg) {
@ -21,7 +35,7 @@ static void test_monotonic(skiatest::Reporter* reporter,
const SkScalar step = SkMaxScalar(width / 10, SK_Scalar1);
for (SkScalar w = 0; w <= width; w += step) {
SkScalar m;
const size_t n = paint.breakText(text, length, w, &m);
const size_t n = break_text(paint, text, length, w, &m, reporter);
REPORTER_ASSERT(reporter, n <= length, msg);
REPORTER_ASSERT(reporter, m <= width, msg);
@ -51,7 +65,7 @@ static void test_eq_measure_text(skiatest::Reporter* reporter,
const SkScalar width = paint.measureText(text, length);
SkScalar mm;
const size_t length2 = paint.breakText(text, length, width, &mm);
const size_t length2 = break_text(paint, text, length, width, &mm, reporter);
REPORTER_ASSERT(reporter, length2 == length, msg);
REPORTER_ASSERT(reporter, mm == width, msg);
}
@ -67,7 +81,7 @@ static void test_long_text(skiatest::Reporter* reporter,
const SkScalar width = paint.measureText(text, kSize);
SkScalar mm;
const size_t length = paint.breakText(text, kSize, width, &mm);
const size_t length = break_text(paint, text, kSize, width, &mm, reporter);
REPORTER_ASSERT(reporter, length == kSize, msg);
REPORTER_ASSERT(reporter, mm == width, msg);
}