aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bench/CmapBench.cpp39
-rw-r--r--bench/TextBench.cpp4
-rw-r--r--fuzz/FuzzCanvas.cpp70
-rw-r--r--include/core/SkCanvas.h5
-rw-r--r--include/core/SkFont.h17
-rw-r--r--include/core/SkPaint.h9
-rw-r--r--src/core/SkCanvas.cpp12
-rw-r--r--src/core/SkFont.cpp38
8 files changed, 141 insertions, 53 deletions
diff --git a/bench/CmapBench.cpp b/bench/CmapBench.cpp
index 49e89bec8c..a89d1aa87b 100644
--- a/bench/CmapBench.cpp
+++ b/bench/CmapBench.cpp
@@ -7,58 +7,49 @@
#include "Benchmark.h"
#include "SkCanvas.h"
-#include "SkPaint.h"
+#include "SkFont.h"
#include "SkTypeface.h"
enum {
NGLYPHS = 100
};
-static SkTypeface::Encoding paint2Encoding(const SkPaint& paint) {
- SkPaint::TextEncoding enc = paint.getTextEncoding();
- SkASSERT(SkPaint::kGlyphID_TextEncoding != enc);
- return (SkTypeface::Encoding)enc;
-}
-
-typedef void (*TypefaceProc)(int loops, const SkPaint&, const void* text, size_t len,
+typedef void (*TypefaceProc)(int loops, const SkFont&, const void* text, size_t len,
int glyphCount);
-static void containsText_proc(int loops, const SkPaint& paint, const void* text, size_t len,
+static void containsText_proc(int loops, const SkFont& font, const void* text, size_t len,
int glyphCount) {
for (int i = 0; i < loops; ++i) {
- paint.containsText(text, len);
+ font.containsText(text, len, kUTF8_SkTextEncoding);
}
}
-static void textToGlyphs_proc(int loops, const SkPaint& paint, const void* text, size_t len,
+static void textToGlyphs_proc(int loops, const SkFont& font, const void* text, size_t len,
int glyphCount) {
uint16_t glyphs[NGLYPHS];
SkASSERT(glyphCount <= NGLYPHS);
for (int i = 0; i < loops; ++i) {
- paint.textToGlyphs(text, len, glyphs);
+ font.textToGlyphs(text, len, kUTF8_SkTextEncoding, glyphs, NGLYPHS);
}
}
-static void charsToGlyphs_proc(int loops, const SkPaint& paint, const void* text,
+static void charsToGlyphs_proc(int loops, const SkFont& font, const void* text,
size_t len, int glyphCount) {
- SkTypeface::Encoding encoding = paint2Encoding(paint);
uint16_t glyphs[NGLYPHS];
SkASSERT(glyphCount <= NGLYPHS);
- SkTypeface* face = paint.getTypeface();
+ SkTypeface* face = font.getTypeface();
for (int i = 0; i < loops; ++i) {
- face->charsToGlyphs(text, encoding, glyphs, glyphCount);
+ face->charsToGlyphs(text, SkTypeface::kUTF8_Encoding, glyphs, glyphCount);
}
}
-static void charsToGlyphsNull_proc(int loops, const SkPaint& paint, const void* text,
+static void charsToGlyphsNull_proc(int loops, const SkFont& font, const void* text,
size_t len, int glyphCount) {
- SkTypeface::Encoding encoding = paint2Encoding(paint);
-
- SkTypeface* face = paint.getTypeface();
+ SkTypeface* face = font.getTypeface();
for (int i = 0; i < loops; ++i) {
- face->charsToGlyphs(text, encoding, nullptr, glyphCount);
+ face->charsToGlyphs(text, SkTypeface::kUTF8_Encoding, nullptr, glyphCount);
}
}
@@ -66,7 +57,7 @@ class CMAPBench : public Benchmark {
TypefaceProc fProc;
SkString fName;
char fText[NGLYPHS];
- SkPaint fPaint;
+ SkFont fFont;
public:
CMAPBench(TypefaceProc proc, const char name[]) {
@@ -77,7 +68,7 @@ public:
// we're jamming values into utf8, so we must keep it legal utf8
fText[i] = 'A' + (i & 31);
}
- fPaint.setTypeface(SkTypeface::MakeDefault());
+ fFont.setTypeface(SkTypeface::MakeDefault());
}
protected:
@@ -86,7 +77,7 @@ protected:
}
void onDraw(int loops, SkCanvas* canvas) override {
- fProc(loops, fPaint, fText, sizeof(fText), NGLYPHS);
+ fProc(loops, fFont, fText, sizeof(fText), NGLYPHS);
}
private:
diff --git a/bench/TextBench.cpp b/bench/TextBench.cpp
index c28f5d77a5..881e78a0a7 100644
--- a/bench/TextBench.cpp
+++ b/bench/TextBench.cpp
@@ -15,6 +15,8 @@
#include "SkTemplates.h"
#include "SkTypeface.h"
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+
enum FontQuality {
kBW,
kAA,
@@ -175,3 +177,5 @@ DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kBW, true); )
DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW, true, true); )
DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA, false, true); )
+
+#endif
diff --git a/fuzz/FuzzCanvas.cpp b/fuzz/FuzzCanvas.cpp
index aea7405a81..7ba19618cf 100644
--- a/fuzz/FuzzCanvas.cpp
+++ b/fuzz/FuzzCanvas.cpp
@@ -877,19 +877,21 @@ static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
}
}
-static void fuzz_paint_text(Fuzz* fuzz, SkPaint* paint) {
- paint->setTypeface( make_fuzz_typeface(fuzz));
- paint->setTextSize( make_fuzz_t<SkScalar>(fuzz));
- paint->setTextScaleX( make_fuzz_t<SkScalar>(fuzz));
- paint->setTextSkewX( make_fuzz_t<SkScalar>(fuzz));
- paint->setLinearText( make_fuzz_t<bool>(fuzz));
- paint->setSubpixelText( make_fuzz_t<bool>(fuzz));
- paint->setLCDRenderText( make_fuzz_t<bool>(fuzz));
- paint->setEmbeddedBitmapText(make_fuzz_t<bool>(fuzz));
- paint->setAutohinted( make_fuzz_t<bool>(fuzz));
- paint->setFakeBoldText( make_fuzz_t<bool>(fuzz));
- paint->setHinting( make_fuzz_t_range<SkFontHinting>(fuzz, 0,
- kFull_SkFontHinting));
+static SkFont fuzz_font(Fuzz* fuzz) {
+ SkFont font;
+ font.setTypeface( make_fuzz_typeface(fuzz));
+ font.setSize( make_fuzz_t<SkScalar>(fuzz));
+ font.setScaleX( make_fuzz_t<SkScalar>(fuzz));
+ font.setSkewX( make_fuzz_t<SkScalar>(fuzz));
+ font.setLinearMetrics( make_fuzz_t<bool>(fuzz));
+ font.setSubpixel( make_fuzz_t<bool>(fuzz));
+ font.setEmbeddedBitmaps( make_fuzz_t<bool>(fuzz));
+ font.setForceAutoHinting( make_fuzz_t<bool>(fuzz));
+ font.setEmbolden( make_fuzz_t<bool>(fuzz));
+ font.setHinting( make_fuzz_t_range<SkFontHinting>(fuzz, 0, kFull_SkFontHinting));
+ font.setEdging( make_fuzz_t_range<SkFont::Edging>(fuzz, 0,
+ (int)SkFont::Edging::kSubpixelAntiAlias));
+ return font;
}
static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
@@ -1041,6 +1043,7 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
return;
}
SkPaint paint;
+ SkFont font;
unsigned drawCommand;
fuzz->nextRange(&drawCommand, 0, 53);
switch (drawCommand) {
@@ -1463,25 +1466,29 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
}
case 45: {
fuzz_paint(fuzz, &paint, depth - 1);
- fuzz_paint_text(fuzz, &paint);
- paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
+ font = fuzz_font(fuzz);
+ SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
SkScalar x, y;
fuzz->next(&x, &y);
- SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
- canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
+ SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+ canvas->drawSimpleText(text.begin(), SkToSizeT(text.count()), encoding, x, y,
+ font, paint);
break;
}
+#ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
case 46: {
fuzz_paint(fuzz, &paint, depth - 1);
- fuzz_paint_text(fuzz, &paint);
- paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
- SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
- int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
+ font = fuzz_font(fuzz);
+ SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
+ SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+ int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
if (glyphCount < 1) {
break;
}
SkAutoTMalloc<SkPoint> pos(glyphCount);
SkAutoTMalloc<SkScalar> widths(glyphCount);
+ font.LEGACY_applyToPaint(&paint);
+ paint.setTextEncoding(encoding);
paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
pos[0] = {0, 0};
for (int i = 1; i < glyphCount; ++i) {
@@ -1494,14 +1501,16 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
}
case 47: {
fuzz_paint(fuzz, &paint, depth - 1);
- fuzz_paint_text(fuzz, &paint);
- paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
- SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
- int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
+ font = fuzz_font(fuzz);
+ SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
+ SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+ int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
SkAutoTMalloc<SkScalar> widths(glyphCount);
if (glyphCount < 1) {
break;
}
+ font.LEGACY_applyToPaint(&paint);
+ paint.setTextEncoding(encoding);
paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
SkScalar x = widths[0];
for (int i = 0; i < glyphCount; ++i) {
@@ -1518,6 +1527,7 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
break;
}
+#endif
case 48: {
// was drawtextonpath
break;
@@ -1526,13 +1536,14 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
// was drawtextonpath
break;
}
+#ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
case 50: {
fuzz_paint(fuzz, &paint, depth - 1);
- fuzz_paint_text(fuzz, &paint);
- paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
+ font = fuzz_font(fuzz);
+ SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
SkRSXform rSXform[kMaxGlyphCount];
- int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
+ int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
SkASSERT(glyphCount <= kMaxGlyphCount);
fuzz->nextN(rSXform, glyphCount);
SkRect cullRect;
@@ -1541,10 +1552,13 @@ static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
if (useCullRect) {
fuzz->next(&cullRect);
}
+ font.LEGACY_applyToPaint(&paint);
+ paint.setTextEncoding(encoding);
canvas->drawTextRSXform(text.begin(), SkToSizeT(text.count()), rSXform,
useCullRect ? &cullRect : nullptr, paint);
break;
}
+#endif
case 51: {
sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
fuzz_paint(fuzz, &paint, depth - 1);
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 6177349044..c0d005fcdc 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -36,6 +36,7 @@ class SkData;
class SkDraw;
class SkDrawable;
struct SkDrawShadowRec;
+class SkFont;
class SkGlyphRunBuilder;
class SkImage;
class SkImageFilter;
@@ -1877,6 +1878,10 @@ public:
void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint);
+ // Experimental
+ void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
+
/** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and
SkPaint paint.
diff --git a/include/core/SkFont.h b/include/core/SkFont.h
index ade29f3242..edf1699c9f 100644
--- a/include/core/SkFont.h
+++ b/include/core/SkFont.h
@@ -291,6 +291,23 @@ public:
return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
}
+ /** Returns true if all text corresponds to a non-zero glyph index.
+ Returns false if any characters in text are not supported in
+ SkTypeface.
+
+ If SkTextEncoding is kGlyphID_SkTextEncoding,
+ returns true if all glyph indices in text are non-zero;
+ does not check to see if text contains valid glyph indices for SkTypeface.
+
+ Returns true if byteLength is zero.
+
+ @param text array of characters or glyphs
+ @param byteLength number of bytes in text array
+ @param encoding text encoding
+ @return true if all text corresponds to a non-zero glyph index
+ */
+ bool containsText(const void* text, size_t byteLength, SkTextEncoding encoding) 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.
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 71492d370c..f9faee89a9 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -54,6 +54,10 @@ class SkTextBlob;
class SkTextBlobRunIterator;
class SkTypeface;
+#ifndef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+#define SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+#endif
+
/** \class SkPaint
SkPaint controls options applied when drawing and measuring. SkPaint collects all
options outside of the SkCanvas clip and SkCanvas matrix.
@@ -953,6 +957,8 @@ public:
this->setTextEncoding((TextEncoding)encoding);
}
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+
#ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
/**
SkFontMetrics is filled out by getFontMetrics(). SkFontMetrics contents reflect the values
@@ -1083,6 +1089,7 @@ public:
SkScalar measureText(const void* text, size_t length) const {
return this->measureText(text, length, nullptr);
}
+#endif
/** Returns the bytes of text that fit within maxWidth.
The text fragment fits if its advance width is less than or equal to maxWidth.
@@ -1101,6 +1108,7 @@ public:
size_t breakText(const void* text, size_t length, SkScalar maxWidth,
SkScalar* measuredWidth = nullptr) const;
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
/** Retrieves the advance and bounds for each glyph in text, and returns
the glyph count in text.
Both widths and bounds may be nullptr.
@@ -1257,6 +1265,7 @@ public:
@return union of bounds of all glyphs
*/
SkRect getFontBounds() const;
+#endif
/** Returns true if SkPaint prevents all drawing;
otherwise, the SkPaint may or may not allow drawing.
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 0ff997cdae..f976d71e20 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2555,7 +2555,17 @@ void SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const
this->drawText(string.c_str(), string.size(), x, y, paint);
}
-// These will become non-virtual, so they always call the (virtual) onDraw... method
+// These call the (virtual) onDraw... method
+void SkCanvas::drawSimpleText(const void* text, size_t byteLength, SkTextEncoding,
+ SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) {
+ TRACE_EVENT0("skia", TRACE_FUNC);
+ if (byteLength) {
+ sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
+ SkPaint tmp(paint);
+ font.LEGACY_applyToPaint(&tmp);
+ this->onDrawText(text, byteLength, x, y, tmp);
+ }
+}
void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp
index 93de69da07..4a29fea944 100644
--- a/src/core/SkFont.cpp
+++ b/src/core/SkFont.cpp
@@ -16,6 +16,7 @@
#include "SkTLazy.h"
#include "SkTypeface.h"
#include "SkUTF.h"
+#include "SkUtils.h"
#define kDefault_Size 12
#define kDefault_Flags 0
@@ -193,6 +194,43 @@ int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding enc
return count;
}
+static SkTypeface::Encoding to_encoding(SkTextEncoding e) {
+ static_assert((int)SkTypeface::kUTF8_Encoding == (int)kUTF8_SkTextEncoding, "");
+ static_assert((int)SkTypeface::kUTF16_Encoding == (int)kUTF16_SkTextEncoding, "");
+ static_assert((int)SkTypeface::kUTF32_Encoding == (int)kUTF32_SkTextEncoding, "");
+ return (SkTypeface::Encoding)e;
+}
+
+bool SkFont::containsText(const void* textData, size_t byteLength, SkTextEncoding textEnc) const {
+ if (0 == byteLength) {
+ return true;
+ }
+
+ SkASSERT(textData != nullptr);
+
+ // handle this encoding before the setup for the glyphcache
+ if (textEnc == kGlyphID_SkTextEncoding) {
+ const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
+ size_t count = byteLength >> 1;
+ for (size_t i = 0; i < count; i++) {
+ if (0 == glyphID[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(*this);
+ const void* stop = (const char*)textData + byteLength;
+ const SkTypeface::Encoding encoding = to_encoding(textEnc);
+ while (textData < stop) {
+ if (0 == cache->unicharToGlyph(SkUTFN_Next(encoding, &textData, stop))) {
+ return false;
+ }
+ }
+ return true;
+}
+
static void set_bounds(const SkGlyph& g, SkRect* bounds) {
bounds->set(SkIntToScalar(g.fLeft),
SkIntToScalar(g.fTop),