From fca302ccf464933e44e00255654d27a7705abb7f Mon Sep 17 00:00:00 2001 From: jvanverth Date: Mon, 20 Oct 2014 13:12:54 -0700 Subject: Add color emoji fallback for distance field text. BUG=skia:3033 Review URL: https://codereview.chromium.org/670533002 --- src/gpu/GrDistanceFieldTextContext.cpp | 65 ++++++++++++++++++++++++---------- src/gpu/GrDistanceFieldTextContext.h | 2 +- 2 files changed, 47 insertions(+), 20 deletions(-) (limited to 'src') 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 fallbackTxt; + SkTArray 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(); -- cgit v1.2.3