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
This commit is contained in:
commit-bot@chromium.org 2014-01-28 22:02:07 +00:00
parent 11ea96c62a
commit e8612d9a8d
9 changed files with 460 additions and 156 deletions

View File

@ -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;

View File

@ -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 {

View File

@ -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 {

View File

@ -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&);
GrTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
GrPaint fPaint;
SkPaint fSkPaint;
GrContext* fContext;
GrDrawTarget* fDrawTarget;
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;
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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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()) {

View File

@ -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;
}

View File

@ -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);
}
}