aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2014-10-20 13:12:54 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-20 13:12:55 -0700
commitfca302ccf464933e44e00255654d27a7705abb7f (patch)
tree10b63a4c4a197460c663393e1430e0f0f16605e4
parentc7eb58c8b46c72cca3cea1582c7f860293a1cbe9 (diff)
Add color emoji fallback for distance field text.
-rw-r--r--expectations/gm/ignored-tests.txt3
-rwxr-xr-xgm/dftext.cpp39
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp65
-rw-r--r--src/gpu/GrDistanceFieldTextContext.h2
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();