diff options
author | jvanverth <jvanverth@google.com> | 2014-10-20 13:12:54 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-20 13:12:55 -0700 |
commit | fca302ccf464933e44e00255654d27a7705abb7f (patch) | |
tree | 10b63a4c4a197460c663393e1430e0f0f16605e4 | |
parent | c7eb58c8b46c72cca3cea1582c7f860293a1cbe9 (diff) |
Add color emoji fallback for distance field text.
BUG=skia:3033
Review URL: https://codereview.chromium.org/670533002
-rw-r--r-- | expectations/gm/ignored-tests.txt | 3 | ||||
-rwxr-xr-x | gm/dftext.cpp | 39 | ||||
-rwxr-xr-x | src/gpu/GrDistanceFieldTextContext.cpp | 65 | ||||
-rw-r--r-- | src/gpu/GrDistanceFieldTextContext.h | 2 |
4 files changed, 77 insertions, 32 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt index 5793ba217b..86cc83ce21 100644 --- a/expectations/gm/ignored-tests.txt +++ b/expectations/gm/ignored-tests.txt @@ -54,3 +54,6 @@ megalooper_0x0 megalooper_1x4 megalooper_4x1 imagefiltersbase + +# jvanverth - adding color emoji to df text +dftext diff --git a/gm/dftext.cpp b/gm/dftext.cpp index 6f75c46713..16fe4bd385 100755 --- a/gm/dftext.cpp +++ b/gm/dftext.cpp @@ -5,30 +5,44 @@ * found in the LICENSE file. */ #include "gm.h" +#include "Resources.h" +#include "SkCanvas.h" +#include "SkStream.h" #include "SkSurface.h" #include "SkTypeface.h" -namespace skiagm { - -class DFTextGM : public GM { +class DFTextGM : public skiagm::GM { public: DFTextGM() { this->setBGColor(0xFFFFFFFF); + fTypeface = NULL; } virtual ~DFTextGM() { + SkSafeUnref(fTypeface); } protected: + virtual void onOnceBeforeDraw() SK_OVERRIDE { + SkString filename = GetResourcePath("/Funkster.ttf"); + SkAutoTUnref<SkFILEStream> stream(new SkFILEStream(filename.c_str())); + if (!stream->isValid()) { + SkDebugf("Could not find Funkster.ttf, please set --resourcePath correctly.\n"); + return; + } + + fTypeface = SkTypeface::CreateFromStream(stream); + } + virtual uint32_t onGetFlags() const SK_OVERRIDE { return kGPUOnly_Flag; } - virtual SkString onShortName() { + virtual SkString onShortName() SK_OVERRIDE { return SkString("dftext"); } - virtual SkISize onISize() { + virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(1024, 768); } @@ -185,6 +199,10 @@ protected: y += paint.getFontMetrics(NULL); } + // check color emoji + paint.setTypeface(fTypeface); + canvas->drawText(text, textLen, 670, 100, paint); + #if SK_SUPPORT_GPU // render offscreen buffer if (surface) { @@ -199,12 +217,9 @@ protected: } private: - typedef GM INHERITED; -}; + SkTypeface* fTypeface; -////////////////////////////////////////////////////////////////////////////// - -static GM* MyFactory(void*) { return new DFTextGM; } -static GMRegistry reg(MyFactory); + typedef skiagm::GM INHERITED; +}; -} +DEF_GM( return SkNEW(DFTextGM); ) diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index 6b047e45d9..dcaee488af 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -294,9 +294,12 @@ void GrDistanceFieldTextContext::onDrawPosText(const GrPaint& paint, const SkPai setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); const char* stop = text + byteLength; + SkTArray<char> fallbackTxt; + SkTArray<SkScalar> fallbackPos; if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { while (text < stop) { + const char* lastText = text; // the last 2 parameters are ignored const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); @@ -304,12 +307,19 @@ void GrDistanceFieldTextContext::onDrawPosText(const GrPaint& paint, const SkPai SkScalar x = offset.x() + pos[0]; SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); - this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkScalarToFixed(x), - SkScalarToFixed(y), - fontScaler); + if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkScalarToFixed(x), + SkScalarToFixed(y), + fontScaler)) { + // couldn't append, send to fallback + fallbackTxt.push_back_n(text-lastText, lastText); + fallbackPos.push_back(pos[0]); + if (2 == scalarsPerPosition) { + fallbackPos.push_back(pos[1]); + } + } } pos += scalarsPerPosition; } @@ -317,6 +327,7 @@ void GrDistanceFieldTextContext::onDrawPosText(const GrPaint& paint, const SkPai SkScalar alignMul = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? SK_ScalarHalf : SK_Scalar1; while (text < stop) { + const char* lastText = text; // the last 2 parameters are ignored const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); @@ -327,18 +338,30 @@ void GrDistanceFieldTextContext::onDrawPosText(const GrPaint& paint, const SkPai SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX)*alignMul*fTextRatio; SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY)*alignMul*fTextRatio; - this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkScalarToFixed(x - advanceX), - SkScalarToFixed(y - advanceY), - fontScaler); + if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkScalarToFixed(x - advanceX), + SkScalarToFixed(y - advanceY), + fontScaler)) { + // couldn't append, send to fallback + fallbackTxt.push_back_n(text-lastText, lastText); + fallbackPos.push_back(pos[0]); + if (2 == scalarsPerPosition) { + fallbackPos.push_back(pos[1]); + } + } } pos += scalarsPerPosition; } } this->finish(); + + if (fallbackTxt.count() > 0) { + fFallbackTextContext->drawPosText(paint, skPaint, fallbackTxt.begin(), fallbackTxt.count(), + fallbackPos.begin(), scalarsPerPosition, offset); + } } static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { @@ -398,11 +421,13 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo } -void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, +// Returns true if this method handled the glyph, false if needs to be passed to fallback +// +bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, SkFixed vx, SkFixed vy, GrFontScaler* scaler) { if (NULL == fDrawTarget) { - return; + return true; } if (NULL == fStrike) { @@ -411,12 +436,12 @@ void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, GrGlyph* glyph = fStrike->getGlyph(packed, scaler); if (NULL == glyph || glyph->fBounds.isEmpty()) { - return; + return true; } - // TODO: support color glyphs + // fallback to color glyph support if (kA8_GrMaskFormat != glyph->fMaskFormat) { - return; + return false; } SkScalar sx = SkFixedToScalar(vx); @@ -474,7 +499,7 @@ void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, if (!scaler->getGlyphPath(glyph->glyphID(), path)) { // flag the glyph as being dead? delete path; - return; + return true; } glyph->fPath = path; } @@ -490,7 +515,7 @@ void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, am.setPreConcat(fContext, ctm, &tmpPaint); GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); - return; + return true; } HAS_ATLAS: @@ -606,6 +631,8 @@ HAS_ATLAS: } fCurrVertex += 4; + + return true; } void GrDistanceFieldTextContext::flush() { diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h index 6fa2d6f173..e0ef7e2e44 100644 --- a/src/gpu/GrDistanceFieldTextContext.h +++ b/src/gpu/GrDistanceFieldTextContext.h @@ -58,7 +58,7 @@ private: const SkPoint& offset) SK_OVERRIDE; void init(const GrPaint&, const SkPaint&); - void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); + bool appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); void setupCoverageEffect(const SkColor& filteredColor); void flush(); // automatically called by destructor void finish(); |