Move distance field font code into GrDistanceFieldTextContext.
This avoids the SkDraw path and renders the distance field glyphs directly from
GrDistanceFieldTextContext. It also disables LCD, subpixel and autohinting, and
removes the supporting code when rendering DF fonts.
R=reed@google.com, bsalomon@google.com, robertphillips@google.com
Author: jvanverth@google.com
Review URL: https://codereview.chromium.org/85653004
git-svn-id: http://skia.googlecode.com/svn/trunk@12770 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 2f67c49..d04e52e 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -9,6 +9,7 @@
#include "GrAtlas.h"
#include "GrDrawTarget.h"
#include "GrFontScaler.h"
+#include "SkGlyphCache.h"
#include "GrIndexBuffer.h"
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
@@ -19,18 +20,16 @@
static const int kGlyphCoordsAttributeIndex = 1;
+static const int kBaseDFFontSize = 32;
+
SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
"Dump the contents of the font cache before every purge.");
-
GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
- const GrPaint& paint,
- SkColor color,
- SkScalar textRatio)
- : GrTextContext(context, paint)
- , fTextRatio(textRatio) {
- fSkPaintColor = color;
-
+ const GrPaint& grPaint,
+ const SkPaint& skPaint)
+ : GrTextContext(context, grPaint),
+ fSkPaint(skPaint) {
fStrike = NULL;
fCurrTexture = NULL;
@@ -38,6 +37,13 @@
fVertices = NULL;
fMaxVertices = 0;
+
+ fTextRatio = fSkPaint.getTextSize()/kBaseDFFontSize;
+
+ fSkPaint.setTextSize(SkIntToScalar(kBaseDFFontSize));
+ fSkPaint.setLCDRenderText(false);
+ fSkPaint.setAutohinted(false);
+ fSkPaint.setSubpixelText(false);
}
GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
@@ -81,11 +87,11 @@
// alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
// the mask texture color. The end result is that we get
// mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
- int a = SkColorGetA(fSkPaintColor);
+ int a = SkColorGetA(fSkPaint.getColor());
// paintAlpha
drawState->setColor(SkColorSetARGB(a, a, a, a));
// paintColor
- drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaintColor));
+ drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
} else {
// set back to normal in case we took LCD path previously.
@@ -276,3 +282,127 @@
2 * sizeof(SkPoint));
fCurrVertex += 4;
}
+
+void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
+ SkScalar x, SkScalar y, SkGlyphCache* cache,
+ GrFontScaler* fontScaler) {
+ SkASSERT(byteLength == 0 || text != NULL);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+ return;
+ }
+
+ SkScalar sizeRatio = fTextRatio;
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ // need to measure first
+ // TODO - generate positions and pre-load cache as well?
+ const char* stop = text + byteLength;
+ if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ SkFixed stopX = 0;
+ SkFixed stopY = 0;
+
+ const char* textPtr = text;
+ while (textPtr < stop) {
+ // don't need x, y here, since all subpixel variants will have the
+ // same advance
+ const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
+
+ stopX += glyph.fAdvanceX;
+ stopY += glyph.fAdvanceY;
+ }
+ SkASSERT(textPtr == stop);
+
+ SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
+ SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
+
+ if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ alignX = SkScalarHalf(alignX);
+ alignY = SkScalarHalf(alignY);
+ }
+
+ x -= alignX;
+ y -= alignY;
+ }
+
+ SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
+ SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
+ SkFixed fixedScale = SkScalarToFixed(sizeRatio);
+ while (text < stop) {
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+
+ fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
+ fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
+ }
+}
+
+void GrDistanceFieldTextContext::drawPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition,
+ SkGlyphCache* cache, GrFontScaler* fontScaler) {
+
+ SkASSERT(byteLength == 0 || text != NULL);
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+ return;
+ }
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ const char* stop = text + byteLength;
+
+ if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkScalar x = pos[0];
+ SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
+ SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkScalar x = pos[0];
+ SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
+ + SK_FixedHalf, //d1g.fHalfSampleX,
+ SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
+ + SK_FixedHalf, //d1g.fHalfSampleY,
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+}
+