From: commit-bot@chromium.org Date: Tue, 28 Jan 2014 22:02:07 +0000 (+0000) Subject: Add standalone drawText for GrTextContext. X-Git-Tag: submit/tizen/20180928.044319~9232 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e8612d9a8d616c2ed0195421a0675e10b0c2d230;p=platform%2Fupstream%2FlibSkiaSharp.git Add standalone drawText for GrTextContext. This unifies the interface between GrBitmapTextContext and GrDistanceFieldTextContext so that they don't need special case code. The future GrNVPRTextContext will also use this interface. BUG=skia:2018 R=bsalomon@google.com, reed@google.com Author: jvanverth@google.com Review URL: https://codereview.chromium.org/141863005 git-svn-id: http://skia.googlecode.com/svn/trunk@13227 2bbb7eff-a529-9590-31e7-b0007b416f81 --- 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; - 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; 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 @@ -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* 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, ¤tText, + 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(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 context(fTextContextManager->create(fContext, grPaint, paint)); - GrDistanceFieldTextContext* dfContext = - static_cast(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 context(fTextContextManager->create(fContext, grPaint, paint)); - myDraw.fProcs = this->initDrawForText(context.get()); - this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint); + SkAutoTDelete 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 context(fTextContextManager->create(fContext, grPaint, paint)); - GrDistanceFieldTextContext* dfContext = - static_cast(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 context(fTextContextManager->create(fContext, grPaint, paint)); - myDraw.fProcs = this->initDrawForText(context.get()); - this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY, - scalarsPerPos, paint); + SkAutoTDelete ctx(fTextContextManager->create(this->context(), + grPaint, paint, + this->getDeviceProperties())); + ctx->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos); } }