Add unit tests to text context

TBR=bsalomon@google.com
BUG=skia:

Review URL: https://codereview.chromium.org/1128153005
This commit is contained in:
joshualitt 2015-05-11 08:58:08 -07:00 committed by Commit bot
parent e590266294
commit 79dfb2b6b6
5 changed files with 194 additions and 60 deletions

View File

@ -9,6 +9,7 @@
#include "GrBatch.h"
#include "GrBatchFontCache.h"
#include "GrBatchTarget.h"
#include "GrBatchTest.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrDrawTarget.h"
#include "GrFontScaler.h"
@ -683,22 +684,22 @@ GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint,
return blob;
}
void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
inline GrAtlasTextContext::BitmapTextBlob*
GrAtlasTextContext::createDrawTextBlob(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
int glyphCount = skPaint.countText(text, byteLength);
SkIRect clipRect;
clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
// setup cache
BitmapTextBlob* blob;
if (this->canDrawAsDistanceFields(skPaint, viewMatrix)) {
SkPaint dfPaint;
SkScalar textRatio;
SkGlyphCache* cache;
SkAutoTUnref<BitmapTextBlob> blob(this->setupDFBlob(glyphCount, skPaint, viewMatrix, &cache,
&dfPaint, &textRatio));
blob = this->setupDFBlob(glyphCount, skPaint, viewMatrix, &cache, &dfPaint, &textRatio);
SkTDArray<char> fallbackTxt;
SkTDArray<SkScalar> fallbackPos;
@ -711,36 +712,36 @@ void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
this->fallbackDrawPosText(blob, 0, rt, clip, paint, skPaint, viewMatrix, fallbackTxt,
fallbackPos, 2, offset, clipRect);
}
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip);
} else {
SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTextVASize));
blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize);
blob->fViewMatrix = viewMatrix;
SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMatrix, false);
this->internalDrawBMPText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text,
byteLength, x, y, clipRect);
SkGlyphCache::AttachCache(cache);
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip);
}
return blob;
}
void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkIRect& regionClipBounds) {
inline GrAtlasTextContext::BitmapTextBlob*
GrAtlasTextContext::createDrawPosTextBlob(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkIRect& regionClipBounds) {
int glyphCount = skPaint.countText(text, byteLength);
SkIRect clipRect;
clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
BitmapTextBlob* blob;
if (this->canDrawAsDistanceFields(skPaint, viewMatrix)) {
SkPaint dfPaint;
SkScalar textRatio;
SkGlyphCache* cache;
SkAutoTUnref<BitmapTextBlob> blob(this->setupDFBlob(glyphCount, skPaint, viewMatrix, &cache,
&dfPaint, &textRatio));
blob = this->setupDFBlob(glyphCount, skPaint, viewMatrix, &cache, &dfPaint, &textRatio);
SkTDArray<char> fallbackTxt;
SkTDArray<SkScalar> fallbackPos;
@ -752,16 +753,41 @@ void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
this->fallbackDrawPosText(blob, 0, rt, clip, paint, skPaint, viewMatrix, fallbackTxt,
fallbackPos, scalarsPerPosition, offset, clipRect);
}
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip);
} else {
SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTextVASize));
blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize);
blob->fViewMatrix = viewMatrix;
SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMatrix, false);
this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text,
byteLength, pos, scalarsPerPosition, offset, clipRect);
SkGlyphCache::AttachCache(cache);
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip);
}
return blob;
}
void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
SkAutoTUnref<BitmapTextBlob> blob(
this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
text, byteLength, x, y, regionClipBounds));
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip);
}
void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkIRect& regionClipBounds) {
SkAutoTUnref<BitmapTextBlob> blob(
this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
text, byteLength,
pos, scalarsPerPosition,
offset, regionClipBounds));
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip);
}
void GrAtlasTextContext::internalDrawBMPText(BitmapTextBlob* blob, int runIndex,
@ -2050,6 +2076,51 @@ void GrAtlasTextContext::flushRunAsPaths(const SkTextBlob::RunIterator& it, cons
}
}
inline BitmapTextBatch*
GrAtlasTextContext::createBatch(BitmapTextBlob* cacheBlob, const PerSubRunInfo& info,
int glyphCount, int run, int subRun,
GrColor color, SkScalar transX, SkScalar transY,
const SkPaint& skPaint) {
GrMaskFormat format = info.fMaskFormat;
GrColor subRunColor;
if (kARGB_GrMaskFormat == format) {
uint8_t paintAlpha = skPaint.getAlpha();
subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha);
} else {
subRunColor = color;
}
BitmapTextBatch* batch;
if (info.fDrawAsDistanceFields) {
SkColor filteredColor;
SkColorFilter* colorFilter = skPaint.getColorFilter();
if (colorFilter) {
filteredColor = colorFilter->filterColor(skPaint.getColor());
} else {
filteredColor = skPaint.getColor();
}
bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry());
float gamma = fDeviceProperties.gamma();
batch = BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFontCache(),
fDistanceAdjustTable, filteredColor,
info.fUseLCDText, useBGR,
gamma);
} else {
batch = BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFontCache());
}
BitmapTextBatch::Geometry& geometry = batch->geometry();
geometry.fBlob = SkRef(cacheBlob);
geometry.fRun = run;
geometry.fSubRun = subRun;
geometry.fColor = subRunColor;
geometry.fTransX = transX;
geometry.fTransY = transY;
batch->init();
return batch;
}
inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder* pipelineBuilder,
BitmapTextBlob* cacheBlob, int run, GrColor color,
SkScalar transX, SkScalar transY, const SkPaint& skPaint) {
@ -2060,42 +2131,9 @@ inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder
continue;
}
GrMaskFormat format = info.fMaskFormat;
GrColor subRunColor;
if (kARGB_GrMaskFormat == format) {
uint8_t paintAlpha = skPaint.getAlpha();
subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha);
} else {
subRunColor = color;
}
SkAutoTUnref<BitmapTextBatch> batch;
if (info.fDrawAsDistanceFields) {
SkColor filteredColor;
SkColorFilter* colorFilter = skPaint.getColorFilter();
if (colorFilter) {
filteredColor = colorFilter->filterColor(skPaint.getColor());
} else {
filteredColor = skPaint.getColor();
}
bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry());
float gamma = fDeviceProperties.gamma();
batch.reset(BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFontCache(),
fDistanceAdjustTable, filteredColor,
info.fUseLCDText, useBGR,
gamma));
} else {
batch.reset(BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFontCache()));
}
BitmapTextBatch::Geometry& geometry = batch->geometry();
geometry.fBlob = SkRef(cacheBlob);
geometry.fRun = run;
geometry.fSubRun = subRun;
geometry.fColor = subRunColor;
geometry.fTransX = transX;
geometry.fTransY = transY;
batch->init();
SkAutoTUnref<BitmapTextBatch> batch(this->createBatch(cacheBlob, info, glyphCount, run,
subRun, color, transX, transY,
skPaint));
target->drawBatch(pipelineBuilder, batch);
}
}
@ -2167,3 +2205,69 @@ void GrAtlasTextContext::flush(GrDrawTarget* target,
// Now flush big glyphs
this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef GR_TEST_UTILS
BATCH_TEST_DEFINE(TextBlob) {
static uint32_t gContextID = SK_InvalidGenID;
static GrAtlasTextContext* gTextContext = NULL;
static SkDeviceProperties gDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
if (context->uniqueID() != gContextID) {
gContextID = context->uniqueID();
SkDELETE(gTextContext);
// We don't yet test the fall back to paths in the GrTextContext base class. This is mostly
// because we don't really want to have a gpu device here.
// We enable distance fields by twiddling a knob on the paint
gTextContext = GrAtlasTextContext::Create(context, NULL, gDeviceProperties, false);
}
// create dummy render target
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = 1024;
desc.fHeight = 1024;
desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fSampleCnt = 1;
SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc, true, NULL, 0));
SkASSERT(texture);
SkASSERT(NULL != texture->asRenderTarget());
GrRenderTarget* rt = texture->asRenderTarget();
// Setup dummy SkPaint / GrPaint
GrColor color = GrRandomColor(random);
SkMatrix viewMatrix = GrTest::TestMatrix(random);
SkPaint skPaint;
skPaint.setDistanceFieldTextTEMP(random->nextBool());
skPaint.setColor(color);
skPaint.setLCDRenderText(random->nextBool());
skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool());
skPaint.setSubpixelText(random->nextBool());
GrPaint grPaint;
if (!SkPaint2GrPaint(context, rt, skPaint, viewMatrix, true, &grPaint)) {
SkFAIL("couldn't convert paint\n");
}
const char* text = "The quick brown fox jumps over the lazy dog.";
int textLen = (int)strlen(text);
// Setup clip
GrClip clip;
SkIRect noClip = SkIRect::MakeLargest();
// right now we don't handle textblobs, nor do we handle drawPosText. Since we only
// intend to test the batch with this unit test, that is okay.
SkAutoTUnref<GrAtlasTextContext::BitmapTextBlob> blob(
gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMatrix, text,
static_cast<size_t>(textLen), 0, 0, noClip));
SkScalar transX = static_cast<SkScalar>(random->nextU());
SkScalar transY = static_cast<SkScalar>(random->nextU());
const GrAtlasTextContext::BitmapTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0];
return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, transY, skPaint);
}
#endif

View File

@ -19,6 +19,11 @@
#include "SkTextBlob.h"
#include "SkTInternalLList.h"
#ifdef GR_TEST_UTILS
#include "GrBatchTest.h"
#endif
class BitmapTextBatch;
class GrPipelineBuilder;
class GrTextBlobCache;
@ -265,6 +270,10 @@ private:
inline void flushRunAsPaths(const SkTextBlob::RunIterator&, const SkPaint&, SkDrawFilter*,
const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
SkScalar y);
inline BitmapTextBatch* createBatch(BitmapTextBlob*, const PerSubRunInfo&,
int glyphCount, int run, int subRun,
GrColor, SkScalar transX, SkScalar transY,
const SkPaint&);
inline void flushRun(GrDrawTarget*, GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
SkScalar transX, SkScalar transY, const SkPaint&);
inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt,
@ -332,6 +341,20 @@ private:
inline void initDistanceFieldPaint(BitmapTextBlob*, SkPaint*, SkScalar* textRatio,
const SkMatrix&);
// Test methods
// TODO this is really ugly. It'd be much nicer if positioning could be moved to batch
inline BitmapTextBlob* createDrawTextBlob(GrRenderTarget*, const GrClip&, const GrPaint&,
const SkPaint&, const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y,
const SkIRect& regionClipBounds);
inline BitmapTextBlob* createDrawPosTextBlob(GrRenderTarget*, const GrClip&, const GrPaint&,
const SkPaint&, const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset,
const SkIRect& regionClipBounds);
// Distance field text needs this table to compute a value for use in the fragment shader.
// Because the GrAtlasTextContext can go out of scope before the final flush, this needs to be
// refcnted and malloced
@ -360,6 +383,10 @@ private:
friend class GrTextBlobCache;
friend class BitmapTextBatch;
#ifdef GR_TEST_UTILS
BATCH_TEST_FRIEND(TextBlob);
#endif
typedef GrTextContext INHERITED;
};

View File

@ -29,7 +29,9 @@ typedef GrBatch* (*BatchTestFunc)(SkRandom* random, GrContext* context);
#define BATCH_TEST_EXTERN(Batch) \
extern GrBatch* Batch##__Test(SkRandom*, GrContext* context);
#define BATCH_TEST_ENTRY(Batch) \
Batch##__Test
Batch##__Test
#define BATCH_TEST_FRIEND(Batch) \
friend GrBatch* Batch##__Test(SkRandom* random, GrContext* context);
GrBatch* GrRandomBatch(SkRandom*, GrContext*);

View File

@ -66,6 +66,7 @@ void GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPai
} while (textContext);
// fall back to drawing as a path
SkASSERT(fGpuDevice);
this->drawTextAsPath(skPaint, viewMatrix, text, byteLength, x, y, clipBounds);
}
@ -89,6 +90,7 @@ void GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const Gr
} while (textContext);
// fall back to drawing as a path
SkASSERT(fGpuDevice);
this->drawPosTextAsPath(skPaint, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset,
clipBounds);
}

View File

@ -12,7 +12,6 @@
#include "GrGlyph.h"
#include "GrPaint.h"
#include "SkDeviceProperties.h"
#include "SkPostConfig.h"
class GrClip;