diff options
-rw-r--r-- | bench/CmapBench.cpp | 39 | ||||
-rw-r--r-- | bench/TextBench.cpp | 4 | ||||
-rw-r--r-- | fuzz/FuzzCanvas.cpp | 70 | ||||
-rw-r--r-- | include/core/SkCanvas.h | 5 | ||||
-rw-r--r-- | include/core/SkFont.h | 17 | ||||
-rw-r--r-- | include/core/SkPaint.h | 9 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 12 | ||||
-rw-r--r-- | src/core/SkFont.cpp | 38 |
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), |