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:
parent
11ea96c62a
commit
e8612d9a8d
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user