aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkPaint.h1
-rwxr-xr-xinclude/gpu/GrBitmapTextContext.h10
-rwxr-xr-xinclude/gpu/GrDistanceFieldTextContext.h19
-rw-r--r--include/gpu/GrTextContext.h51
-rw-r--r--include/gpu/SkGpuDevice.h2
-rwxr-xr-xsrc/gpu/GrBitmapTextContext.cpp340
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp32
-rw-r--r--src/gpu/GrTextContext.cpp55
-rw-r--r--src/gpu/SkGpuDevice.cpp110
9 files changed, 462 insertions, 158 deletions
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index ab93eac102..00ec29e42e 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -1071,6 +1071,7 @@ private:
friend class SkDraw;
friend class SkGraphics; // So Term() can be called.
friend class SkPDFDevice;
+ friend class GrBitmapTextContext;
friend class GrDistanceFieldTextContext;
friend class SkTextToPathIter;
friend class SkCanonicalizePaint;
diff --git a/include/gpu/GrBitmapTextContext.h b/include/gpu/GrBitmapTextContext.h
index e1b3d725a9..c66f8a8564 100755
--- a/include/gpu/GrBitmapTextContext.h
+++ b/include/gpu/GrBitmapTextContext.h
@@ -17,17 +17,19 @@ class GrTextStrike;
*/
class GrBitmapTextContext : public GrTextContext {
public:
- virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
- GrFontScaler*) SK_OVERRIDE;
+ virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE;
+ virtual void drawPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) SK_OVERRIDE;
private:
- GrBitmapTextContext(GrContext*, const GrPaint&, const SkPaint&);
+ GrBitmapTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
virtual ~GrBitmapTextContext();
friend class GrTTextContextManager<GrBitmapTextContext>;
- GrContext::AutoMatrix fAutoMatrix;
GrTextStrike* fStrike;
+ void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, GrFontScaler*);
void flushGlyphs(); // automatically called by destructor
enum {
diff --git a/include/gpu/GrDistanceFieldTextContext.h b/include/gpu/GrDistanceFieldTextContext.h
index 4fde6ceef8..79058b8bbd 100755
--- a/include/gpu/GrDistanceFieldTextContext.h
+++ b/include/gpu/GrDistanceFieldTextContext.h
@@ -17,26 +17,21 @@ class GrTextStrike;
*/
class GrDistanceFieldTextContext : public GrTextContext {
public:
- virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
- GrFontScaler*) SK_OVERRIDE;
-
- void drawText(const char text[], size_t byteLength,
- SkScalar x, SkScalar y, SkGlyphCache*, GrFontScaler*);
- void drawPosText(const char text[], size_t byteLength,
- const SkScalar pos[], SkScalar constY,
- int scalarsPerPosition,
- SkGlyphCache* cache, GrFontScaler* fontScaler);
-
- const SkPaint& getSkPaint() { return fSkPaint; }
+ virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE;
+ virtual void drawPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) SK_OVERRIDE;
private:
- GrDistanceFieldTextContext(GrContext*, const GrPaint&, const SkPaint&);
+ GrDistanceFieldTextContext(GrContext*, const GrPaint&, const SkPaint&,
+ const SkDeviceProperties&);
virtual ~GrDistanceFieldTextContext();
friend class GrTTextContextManager<GrDistanceFieldTextContext>;
GrTextStrike* fStrike;
SkScalar fTextRatio;
+ void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, GrFontScaler*);
void flushGlyphs(); // automatically called by destructor
enum {
diff --git a/include/gpu/GrTextContext.h b/include/gpu/GrTextContext.h
index 1539df09a0..a8c0df0bda 100644
--- a/include/gpu/GrTextContext.h
+++ b/include/gpu/GrTextContext.h
@@ -8,9 +8,10 @@
#ifndef GrTextContext_DEFINED
#define GrTextContext_DEFINED
-#include "GrContext.h"
+#include "GrPoint.h"
#include "GrGlyph.h"
#include "GrPaint.h"
+#include "SkDeviceProperties.h"
#include "SkPostConfig.h"
@@ -24,18 +25,25 @@ class GrFontScaler;
class GrTextContext {
public:
virtual ~GrTextContext() {}
- virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
- GrFontScaler*) = 0;
+ virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) = 0;
+ virtual void drawPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) = 0;
protected:
- GrTextContext(GrContext*, const GrPaint&, const SkPaint&);
-
- GrPaint fPaint;
- SkPaint fSkPaint;
- GrContext* fContext;
- GrDrawTarget* fDrawTarget;
-
- SkIRect fClipRect;
+ GrTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
+
+ static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
+ static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+ const char text[], size_t byteLength, SkVector* stopVector);
+
+ GrContext* fContext;
+ GrPaint fPaint;
+ SkPaint fSkPaint;
+ SkDeviceProperties fDeviceProperties;
+ GrDrawTarget* fDrawTarget;
+
+ SkIRect fClipRect;
};
/*
@@ -45,8 +53,8 @@ protected:
class GrTextContextManager {
public:
virtual ~GrTextContextManager() {}
- virtual GrTextContext* create(GrContext* context, const GrPaint& grPaint,
- const SkPaint& skPaint) = 0;
+ virtual GrTextContext* create(GrContext* grContext, const GrPaint& grPaint,
+ const SkPaint& skPaint, const SkDeviceProperties& props) = 0;
};
template <class TextContextClass>
@@ -54,13 +62,14 @@ class GrTTextContextManager : public GrTextContextManager {
private:
class ManagedTextContext : public TextContextClass {
public:
- ~ManagedTextContext() {}
+ virtual ~ManagedTextContext() {}
- ManagedTextContext(GrContext* context,
+ ManagedTextContext(GrContext* grContext,
const GrPaint& grPaint,
const SkPaint& skPaint,
+ const SkDeviceProperties& properties,
GrTTextContextManager<TextContextClass>* manager) :
- TextContextClass(context, grPaint, skPaint) {
+ TextContextClass(grContext, grPaint, skPaint, properties) {
fManager = manager;
}
@@ -84,17 +93,19 @@ public:
fUsed = false;
}
- ~GrTTextContextManager() {
+ virtual ~GrTTextContextManager() {
SkASSERT(!fUsed);
sk_free(fAllocation);
}
- GrTextContext* create(GrContext* context, const GrPaint& grPaint,
- const SkPaint& skPaint) {
+ virtual GrTextContext* create(GrContext* grContext, const GrPaint& grPaint,
+ const SkPaint& skPaint, const SkDeviceProperties& properties)
+ SK_OVERRIDE {
// add check for usePath here?
SkASSERT(!fUsed);
ManagedTextContext* obj = SkNEW_PLACEMENT_ARGS(fAllocation, ManagedTextContext,
- (context, grPaint, skPaint, this));
+ (grContext, grPaint, skPaint, properties,
+ this));
fUsed = true;
return obj;
}
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 2888951e47..addf678654 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -167,8 +167,6 @@ private:
bool isOpaque,
Usage usage) SK_OVERRIDE;
- SkDrawProcs* initDrawForText(GrTextContext*);
-
// sets the render target, clip, and matrix on GrContext. Use forceIdenity to override
// SkDraw's matrix and draw in device coords.
void prepareDraw(const SkDraw&, bool forceIdentity);
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 6e33d90d07..da887a5456 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -18,16 +18,21 @@
#include "SkStrokeRec.h"
#include "effects/GrCustomCoordsTextureEffect.h"
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGpuDevice.h"
+#include "SkGr.h"
+
static const int kGlyphCoordsAttributeIndex = 1;
SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
"Dump the contents of the font cache before every purge.");
-GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& paint,
- const SkPaint& skPaint) :
- GrTextContext(context, paint, skPaint) {
- fAutoMatrix.setIdentity(fContext, &fPaint);
-
+GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
+ const GrPaint& grPaint,
+ const SkPaint& skPaint,
+ const SkDeviceProperties& properties)
+ : GrTextContext(context, grPaint, skPaint, properties) {
fStrike = NULL;
fCurrTexture = NULL;
@@ -107,6 +112,330 @@ void GrBitmapTextContext::flushGlyphs() {
}
}
+void GrBitmapTextContext::drawText(const char text[], size_t byteLength,
+ SkScalar x, SkScalar y) {
+ SkASSERT(byteLength == 0 || text != NULL);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
+ return;
+ }
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ // transform our starting point
+ {
+ SkPoint loc;
+ fContext->getMatrix().mapXY(x, y, &loc);
+ x = loc.fX;
+ y = loc.fY;
+ }
+
+ // need to measure first
+ if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ SkVector stop;
+
+ MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+
+ SkScalar stopX = stop.fX;
+ SkScalar stopY = stop.fY;
+
+ if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ stopX = SkScalarHalf(stopX);
+ stopY = SkScalarHalf(stopY);
+ }
+ x -= stopX;
+ y -= stopY;
+ }
+
+ const char* stop = text + byteLength;
+
+ SkAutoKern autokern;
+
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
+ SkFixed halfSampleX, halfSampleY;
+ if (cache->isSubpixel()) {
+ halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
+ SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
+ if (kX_SkAxisAlignment == baseline) {
+ fyMask = 0;
+ halfSampleY = SK_FixedHalf;
+ } else if (kY_SkAxisAlignment == baseline) {
+ fxMask = 0;
+ halfSampleX = SK_FixedHalf;
+ }
+ } else {
+ halfSampleX = halfSampleY = SK_FixedHalf;
+ }
+
+ SkFixed fx = SkScalarToFixed(x) + halfSampleX;
+ SkFixed fy = SkScalarToFixed(y) + halfSampleY;
+
+ GrContext::AutoMatrix autoMatrix;
+ autoMatrix.setIdentity(fContext, &fPaint);
+
+ while (text < stop) {
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
+
+ fx += autokern.adjust(glyph);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+
+ fx += glyph.fAdvanceX;
+ fy += glyph.fAdvanceY;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Copied from SkDraw
+
+// last parameter is interpreted as SkFixed [x, y]
+// return the fixed position, which may be rounded or not by the caller
+// e.g. subpixel doesn't round
+typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
+
+static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+ dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
+}
+
+static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+ dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
+ SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
+}
+
+static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+ dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
+ SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
+}
+
+static AlignProc pick_align_proc(SkPaint::Align align) {
+ static const AlignProc gProcs[] = {
+ leftAlignProc, centerAlignProc, rightAlignProc
+ };
+
+ SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
+
+ return gProcs[align];
+}
+
+class BitmapTextMapState {
+public:
+ mutable SkPoint fLoc;
+
+ BitmapTextMapState(const SkMatrix& matrix, SkScalar y)
+ : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
+
+ typedef void (*Proc)(const BitmapTextMapState&, const SkScalar pos[]);
+
+ Proc pickProc(int scalarsPerPosition);
+
+private:
+ const SkMatrix& fMatrix;
+ SkMatrix::MapXYProc fProc;
+ SkScalar fY; // ignored by MapXYProc
+ // these are only used by Only... procs
+ SkScalar fScaleX, fTransX, fTransformedY;
+
+ static void MapXProc(const BitmapTextMapState& state, const SkScalar pos[]) {
+ state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
+ }
+
+ static void MapXYProc(const BitmapTextMapState& state, const SkScalar pos[]) {
+ state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
+ }
+
+ static void MapOnlyScaleXProc(const BitmapTextMapState& state,
+ const SkScalar pos[]) {
+ state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
+ state.fTransformedY);
+ }
+
+ static void MapOnlyTransXProc(const BitmapTextMapState& state,
+ const SkScalar pos[]) {
+ state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
+ }
+};
+
+BitmapTextMapState::Proc BitmapTextMapState::pickProc(int scalarsPerPosition) {
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+ if (1 == scalarsPerPosition) {
+ unsigned mtype = fMatrix.getType();
+ if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
+ return MapXProc;
+ } else {
+ fScaleX = fMatrix.getScaleX();
+ fTransX = fMatrix.getTranslateX();
+ fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
+ fMatrix.getTranslateY();
+ return (mtype & SkMatrix::kScale_Mask) ?
+ MapOnlyScaleXProc : MapOnlyTransXProc;
+ }
+ } else {
+ return MapXYProc;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrBitmapTextContext::drawPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) {
+ SkASSERT(byteLength == 0 || text != NULL);
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
+ return;
+ }
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ // store original matrix before we reset, so we can use it to transform positions
+ SkMatrix ctm = fContext->getMatrix();
+ GrContext::AutoMatrix autoMatrix;
+ autoMatrix.setIdentity(fContext, &fPaint);
+
+ const char* stop = text + byteLength;
+ AlignProc alignProc = pick_align_proc(fSkPaint.getTextAlign());
+ BitmapTextMapState tms(ctm, constY);
+ BitmapTextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
+ SkFixed halfSampleX = 0, halfSampleY = 0;
+
+ if (cache->isSubpixel()) {
+ // maybe we should skip the rounding if linearText is set
+ SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
+
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
+ if (kX_SkAxisAlignment == baseline) {
+ fyMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+ halfSampleY = SK_FixedHalf;
+#endif
+ } else if (kY_SkAxisAlignment == baseline) {
+ fxMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+ halfSampleX = SK_FixedHalf;
+#endif
+ }
+
+ if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+ while (text < stop) {
+ tmsProc(tms, pos);
+ SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + halfSampleX;
+ SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + halfSampleY;
+
+ const SkGlyph& glyph = glyphCacheProc(cache, &text,
+ fx & fxMask, fy & fyMask);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ while (text < stop) {
+ const char* currentText = text;
+ const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (metricGlyph.fWidth) {
+ SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
+ SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
+
+ tmsProc(tms, pos);
+ SkIPoint fixedLoc;
+ alignProc(tms.fLoc, metricGlyph, &fixedLoc);
+
+ SkFixed fx = fixedLoc.fX + halfSampleX;
+ SkFixed fy = fixedLoc.fY + halfSampleY;
+
+ // have to call again, now that we've been "aligned"
+ const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
+ fx & fxMask, fy & fyMask);
+ // the assumption is that the metrics haven't changed
+ SkASSERT(prevAdvX == glyph.fAdvanceX);
+ SkASSERT(prevAdvY == glyph.fAdvanceY);
+ SkASSERT(glyph.fWidth);
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+ } else { // not subpixel
+
+ 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) {
+ tmsProc(tms, pos);
+
+ SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf; //halfSampleX;
+ SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf; //halfSampleY;
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ tmsProc(tms, pos);
+
+ SkIPoint fixedLoc;
+ alignProc(tms.fLoc, glyph, &fixedLoc);
+
+ SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
+ SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+ }
+}
+
namespace {
// position + texture coord
@@ -123,6 +452,7 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
if (NULL == fDrawTarget) {
return;
}
+
if (NULL == fStrike) {
#if SK_DISTANCEFIELD_FONTS
fStrike = fContext->getFontCache()->getStrike(scaler, false);
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 4c9631e146..afb203aaf9 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -13,6 +13,7 @@
#include "GrIndexBuffer.h"
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
+#include "SkGpuDevice.h"
#include "SkPath.h"
#include "SkRTConf.h"
#include "SkStrokeRec.h"
@@ -25,10 +26,11 @@ 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,
+GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
const GrPaint& grPaint,
- const SkPaint& skPaint)
- : GrTextContext(context, grPaint, skPaint) {
+ const SkPaint& skPaint,
+ const SkDeviceProperties& properties)
+ : GrTextContext(context, grPaint, skPaint, properties) {
fStrike = NULL;
fCurrTexture = NULL;
@@ -283,19 +285,23 @@ HAS_ATLAS:
}
void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
- SkScalar x, SkScalar y, SkGlyphCache* cache,
- GrFontScaler* fontScaler) {
+ SkScalar x, SkScalar y) {
SkASSERT(byteLength == 0 || text != NULL);
- // nothing to draw
- if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+ // nothing to draw or can't draw
+ if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+ || fSkPaint.getRasterizer()) {
return;
}
-
+
SkScalar sizeRatio = fTextRatio;
SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
// need to measure first
// TODO - generate positions and pre-load cache as well?
const char* stop = text + byteLength;
@@ -348,19 +354,23 @@ void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
void GrDistanceFieldTextContext::drawPosText(const char text[], size_t byteLength,
const SkScalar pos[], SkScalar constY,
- int scalarsPerPosition,
- SkGlyphCache* cache, GrFontScaler* fontScaler) {
+ int scalarsPerPosition) {
SkASSERT(byteLength == 0 || text != NULL);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
// nothing to draw
- if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+ if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+ || fSkPaint.getRasterizer()) {
return;
}
SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
const char* stop = text + byteLength;
if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 77e98d2fd5..ab9ef85f1d 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -5,12 +5,17 @@
* found in the LICENSE file.
*/
-
#include "GrTextContext.h"
+#include "GrContext.h"
+
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGr.h"
GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint,
- const SkPaint& skPaint) : fPaint(paint), fSkPaint(skPaint) {
- fContext = context;
+ const SkPaint& skPaint, const SkDeviceProperties& properties) :
+ fContext(context), fPaint(paint), fSkPaint(skPaint),
+ fDeviceProperties(properties) {
const GrClipData* clipData = context->getClip();
@@ -24,5 +29,47 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint,
devConservativeBound.roundOut(&fClipRect);
- fDrawTarget = fContext->getTextTarget();
+ fDrawTarget = context->getTextTarget();
}
+
+//*** change to output positions?
+void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+ const char text[], size_t byteLength, SkVector* stopVector) {
+ SkFixed x = 0, y = 0;
+ const char* stop = text + byteLength;
+
+ SkAutoKern autokern;
+
+ while (text < stop) {
+ // don't need x, y here, since all subpixel variants will have the
+ // same advance
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ x += autokern.adjust(glyph) + glyph.fAdvanceX;
+ y += glyph.fAdvanceY;
+ }
+ stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
+
+ SkASSERT(text == stop);
+}
+
+static void GlyphCacheAuxProc(void* data) {
+ GrFontScaler* scaler = (GrFontScaler*)data;
+ SkSafeUnref(scaler);
+}
+
+GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) {
+ void* auxData;
+ GrFontScaler* scaler = NULL;
+
+ if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
+ scaler = (GrFontScaler*)auxData;
+ }
+ if (NULL == scaler) {
+ scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
+ cache->setAuxProc(GlyphCacheAuxProc, scaler);
+ }
+
+ return scaler;
+}
+
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 73eb65b661..f52385ad7b 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1766,58 +1766,6 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
///////////////////////////////////////////////////////////////////////////////
-static void GlyphCacheAuxProc(void* data) {
- GrFontScaler* scaler = (GrFontScaler*)data;
- SkSafeUnref(scaler);
-}
-
-static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
- void* auxData;
- GrFontScaler* scaler = NULL;
- if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
- scaler = (GrFontScaler*)auxData;
- }
- if (NULL == scaler) {
- scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
- cache->setAuxProc(GlyphCacheAuxProc, scaler);
- }
- return scaler;
-}
-
-static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
- SkFixed fx, SkFixed fy,
- const SkGlyph& glyph) {
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
-
- GrSkDrawProcs* procs = static_cast<GrSkDrawProcs*>(state.fDraw->fProcs);
-
- if (NULL == procs->fFontScaler) {
- procs->fFontScaler = get_gr_font_scaler(state.fCache);
- }
-
- procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed()),
- SkFixedFloorToFixed(fx),
- SkFixedFloorToFixed(fy),
- procs->fFontScaler);
-}
-
-SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
-
- // deferred allocation
- if (NULL == fDrawProcs) {
- fDrawProcs = SkNEW(GrSkDrawProcs);
- fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
- fDrawProcs->fContext = fContext;
- }
-
- // init our (and GL's) state
- fDrawProcs->fTextContext = context;
- fDrawProcs->fFontScaler = NULL;
- return fDrawProcs;
-}
-
void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
@@ -1825,8 +1773,7 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
-#if SK_DISTANCEFIELD_FONTS
- } else if (!paint.getRasterizer()) {
+ } else {
GrPaint grPaint;
if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
return;
@@ -1834,27 +1781,10 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
SkDEBUGCODE(this->validate();)
- SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
- GrDistanceFieldTextContext* dfContext =
- static_cast<GrDistanceFieldTextContext*>(context.get());
-
- SkAutoGlyphCache autoCache(dfContext->getSkPaint(), &this->fLeakyProperties, NULL);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* fontScaler = get_gr_font_scaler(cache);
-
- dfContext->drawText((const char *)text, byteLength, x, y, cache, fontScaler);
-#endif
- } else {
- SkDraw myDraw(draw);
-
- GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
-
- SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
- myDraw.fProcs = this->initDrawForText(context.get());
- this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
+ SkAutoTDelete<GrTextContext> ctx(fTextContextManager->create(this->context(),
+ grPaint, paint,
+ this->getDeviceProperties()));
+ ctx->drawText((const char *)text, byteLength, x, y);
}
}
@@ -1868,8 +1798,7 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
// this guy will just call our drawPath()
draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
scalarsPerPos, paint);
-#if SK_DISTANCEFIELD_FONTS
- } else if (!paint.getRasterizer()) {
+ } else {
GrPaint grPaint;
if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
return;
@@ -1877,29 +1806,10 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
SkDEBUGCODE(this->validate();)
- SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
- GrDistanceFieldTextContext* dfContext =
- static_cast<GrDistanceFieldTextContext*>(context.get());
-
- SkAutoGlyphCache autoCache(dfContext->getSkPaint(), &this->fLeakyProperties, NULL);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* fontScaler = get_gr_font_scaler(cache);
-
- dfContext->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos,
- cache, fontScaler);
-#endif
- } else {
- SkDraw myDraw(draw);
-
- GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
-
- SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
- myDraw.fProcs = this->initDrawForText(context.get());
- this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
- scalarsPerPos, paint);
+ SkAutoTDelete<GrTextContext> ctx(fTextContextManager->create(this->context(),
+ grPaint, paint,
+ this->getDeviceProperties()));
+ ctx->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos);
}
}