remove old text contexts and fontcache
BUG=skia:
Review URL: https://codereview.chromium.org/1104343003
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index 8e4b663..c2c76ed 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -6,7 +6,6 @@
*/
#include "GrAtlasTextContext.h"
-#include "GrAtlas.h"
#include "GrBatch.h"
#include "GrBatchFontCache.h"
#include "GrBatchTarget.h"
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
deleted file mode 100755
index efce516..0000000
--- a/src/gpu/GrBitmapTextContext.cpp
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "GrBitmapTextContext.h"
-
-#include "GrAtlas.h"
-#include "GrBatch.h"
-#include "GrBatchFontCache.h"
-#include "GrBatchTarget.h"
-#include "GrDefaultGeoProcFactory.h"
-#include "GrDrawTarget.h"
-#include "GrFontCache.h"
-#include "GrFontScaler.h"
-#include "GrIndexBuffer.h"
-#include "GrStrokeInfo.h"
-#include "GrTexturePriv.h"
-
-#include "SkAutoKern.h"
-#include "SkColorPriv.h"
-#include "SkDraw.h"
-#include "SkDrawFilter.h"
-#include "SkDrawProcs.h"
-#include "SkGlyphCache.h"
-#include "SkGpuDevice.h"
-#include "SkGr.h"
-#include "SkPath.h"
-#include "SkRTConf.h"
-#include "SkStrokeRec.h"
-#include "SkTextBlob.h"
-#include "SkTextMapStateProc.h"
-
-#include "effects/GrBitmapTextGeoProc.h"
-#include "effects/GrSimpleTextureEffect.h"
-
-SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
- "Dump the contents of the font cache before every purge.");
-
-namespace {
-static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
-
-// position + local coord
-static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
-
-static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
-
-static const int kVerticesPerGlyph = 4;
-static const int kIndicesPerGlyph = 6;
-
-static size_t get_vertex_stride(GrMaskFormat maskFormat) {
- switch (maskFormat) {
- case kA8_GrMaskFormat:
- return kGrayTextVASize;
- case kARGB_GrMaskFormat:
- return kColorTextVASize;
- default:
- return kLCDTextVASize;
- }
-}
-
-};
-
-GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
- SkGpuDevice* gpuDevice,
- const SkDeviceProperties& properties)
- : GrTextContext(context, gpuDevice, properties) {
- fStrike = NULL;
-
- fCurrTexture = NULL;
- fEffectTextureUniqueID = SK_InvalidUniqueID;
-
- fVertices = NULL;
- fCurrVertex = 0;
- fAllocVertexCount = 0;
- fTotalVertexCount = 0;
-
- fVertexBounds.setLargestInverted();
-}
-
-GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
- SkGpuDevice* gpuDevice,
- const SkDeviceProperties& props) {
- return SkNEW_ARGS(GrBitmapTextContext, (context, gpuDevice, props));
-}
-
-bool GrBitmapTextContext::canDraw(const GrRenderTarget* rt,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix) {
- return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
-}
-
-inline void GrBitmapTextContext::init(GrRenderTarget* rt, const GrClip& clip,
- const GrPaint& paint, const SkPaint& skPaint,
- const SkIRect& regionClipBounds) {
- GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds);
-
- fStrike = NULL;
-
- fCurrTexture = NULL;
- fCurrVertex = 0;
-
- fVertices = NULL;
- fAllocVertexCount = 0;
- fTotalVertexCount = 0;
-}
-
-void GrBitmapTextContext::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) {
- SkASSERT(byteLength == 0 || text != NULL);
-
- // nothing to draw
- if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
- return;
- }
-
- this->init(rt, clip, paint, skPaint, regionClipBounds);
-
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
-
- SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &viewMatrix);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* fontScaler = GetGrFontScaler(cache);
-
- // transform our starting point
- {
- SkPoint loc;
- viewMatrix.mapXY(x, y, &loc);
- x = loc.fX;
- y = loc.fY;
- }
-
- // need to measure first
- int numGlyphs;
- if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
- SkVector stopVector;
- numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector);
-
- SkScalar stopX = stopVector.fX;
- SkScalar stopY = stopVector.fY;
-
- if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
- stopX = SkScalarHalf(stopX);
- stopY = SkScalarHalf(stopY);
- }
- x -= stopX;
- y -= stopY;
- } else {
- numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
- }
- fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
-
- const char* stop = text + byteLength;
-
- SkAutoKern autokern;
-
- SkFixed fxMask = ~0;
- SkFixed fyMask = ~0;
- SkScalar halfSampleX, halfSampleY;
- if (cache->isSubpixel()) {
- halfSampleX = halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
- SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
- if (kX_SkAxisAlignment == baseline) {
- fyMask = 0;
- halfSampleY = SK_ScalarHalf;
- } else if (kY_SkAxisAlignment == baseline) {
- fxMask = 0;
- halfSampleX = SK_ScalarHalf;
- }
- } else {
- halfSampleX = halfSampleY = SK_ScalarHalf;
- }
-
- Sk48Dot16 fx = SkScalarTo48Dot16(x + halfSampleX);
- Sk48Dot16 fy = SkScalarTo48Dot16(y + halfSampleY);
-
- // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix, but for
- // performance reasons we just invert here instead
- if (!viewMatrix.invert(&fLocalMatrix)) {
- SkDebugf("Cannot invert viewmatrix\n");
- return;
- }
-
- while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
-
- fx += autokern.adjust(glyph);
-
- if (glyph.fWidth) {
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler);
- }
-
- fx += glyph.fAdvanceX;
- fy += glyph.fAdvanceY;
- }
-
- this->finish();
-}
-
-void GrBitmapTextContext::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) {
- SkASSERT(byteLength == 0 || text != NULL);
- SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
-
- // nothing to draw
- if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
- return;
- }
-
- this->init(rt, clip, paint, skPaint, regionClipBounds);
-
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
-
- SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &viewMatrix);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* fontScaler = GetGrFontScaler(cache);
-
- // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix, but for
- // performance reasons we just invert here instead
- if (!viewMatrix.invert(&fLocalMatrix)) {
- SkDebugf("Cannot invert viewmatrix\n");
- return;
- }
-
- int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
- fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
-
- const char* stop = text + byteLength;
- SkTextAlignProc alignProc(fSkPaint.getTextAlign());
- SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition);
-
- if (cache->isSubpixel()) {
- // maybe we should skip the rounding if linearText is set
- SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
-
- SkFixed fxMask = ~0;
- SkFixed fyMask = ~0;
- SkScalar halfSampleX = SkFixedToScalar(SkGlyph::kSubpixelRound);
- SkScalar halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
- if (kX_SkAxisAlignment == baseline) {
- fyMask = 0;
- halfSampleY = SK_ScalarHalf;
- } else if (kY_SkAxisAlignment == baseline) {
- fxMask = 0;
- halfSampleX = SK_ScalarHalf;
- }
-
- if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
- while (text < stop) {
- SkPoint tmsLoc;
- tmsProc(pos, &tmsLoc);
- Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + halfSampleX);
- Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + halfSampleY);
-
- const SkGlyph& glyph = glyphCacheProc(cache, &text,
- fx & fxMask, fy & fyMask);
-
- if (glyph.fWidth) {
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(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;)
- SkPoint tmsLoc;
- tmsProc(pos, &tmsLoc);
- SkPoint alignLoc;
- alignProc(tmsLoc, metricGlyph, &alignLoc);
-
- Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + halfSampleX);
- Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.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->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(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) {
- SkPoint tmsLoc;
- tmsProc(pos, &tmsLoc);
-
- Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf);
- Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf);
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(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) {
- SkPoint tmsLoc;
- tmsProc(pos, &tmsLoc);
-
- SkPoint alignLoc;
- alignProc(tmsLoc, glyph, &alignLoc);
-
- Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf);
- Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf);
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler);
- }
- pos += scalarsPerPosition;
- }
- }
- }
-
- this->finish();
-}
-
-static void* alloc_vertices(GrDrawTarget* drawTarget,
- int numVertices,
- GrMaskFormat maskFormat) {
- if (numVertices <= 0) {
- return NULL;
- }
-
- // set up attributes
- void* vertices = NULL;
- bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
- get_vertex_stride(maskFormat),
- 0,
- &vertices,
- NULL);
- GrAlwaysAssert(success);
- return vertices;
-}
-
-inline bool GrBitmapTextContext::uploadGlyph(GrGlyph* glyph, GrFontScaler* scaler) {
- if (!fStrike->glyphTooLargeForAtlas(glyph)) {
- if (fStrike->addGlyphToAtlas(glyph, scaler)) {
- return true;
- }
-
- // try to clear out an unused plot before we flush
- if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- return true;
- }
-
- if (c_DumpFontCache) {
-#ifdef SK_DEVELOPER
- fContext->getFontCache()->dump();
-#endif
- }
-
- // before we purge the cache, we must flush any accumulated draws
- this->flush();
- fContext->flush();
-
- // we should have an unused plot now
- if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- return true;
- }
-
- // we should never get here
- SkASSERT(false);
- }
-
- return false;
-}
-
-void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
- int vx, int vy,
- GrFontScaler* scaler) {
- if (NULL == fDrawTarget) {
- return;
- }
-
- if (NULL == fStrike) {
- fStrike = fContext->getFontCache()->getStrike(scaler);
- }
-
- GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
- if (NULL == glyph || glyph->fBounds.isEmpty()) {
- return;
- }
-
- int x = vx + glyph->fBounds.fLeft;
- int y = vy + glyph->fBounds.fTop;
-
- // keep them as ints until we've done the clip-test
- int width = glyph->fBounds.width();
- int height = glyph->fBounds.height();
-
- // check if we clipped out
- if (fClipRect.quickReject(x, y, x + width, y + height)) {
- return;
- }
-
- // If the glyph is too large we fall back to paths
- if (NULL == glyph->fPlot && !uploadGlyph(glyph, scaler)) {
- if (NULL == glyph->fPath) {
- SkPath* path = SkNEW(SkPath);
- if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
- // flag the glyph as being dead?
- delete path;
- return;
- }
- glyph->fPath = path;
- }
-
- // flush any accumulated draws before drawing this glyph as a path.
- this->flush();
-
- SkMatrix translate;
- translate.setTranslate(SkIntToScalar(vx), SkIntToScalar(vy));
- SkPath tmpPath(*glyph->fPath);
- tmpPath.transform(translate);
- GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
- fContext->drawPath(fRenderTarget, fClip, fPaint, SkMatrix::I(), tmpPath, strokeInfo);
-
- // remove this glyph from the vertices we need to allocate
- fTotalVertexCount -= kVerticesPerGlyph;
- return;
- }
-
- SkASSERT(glyph->fPlot);
- GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
- glyph->fPlot->setDrawToken(drawToken);
-
- // the current texture/maskformat must match what the glyph needs
- GrTexture* texture = glyph->fPlot->texture();
- SkASSERT(texture);
-
- if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fAllocVertexCount) {
- this->flush();
- fCurrTexture = texture;
- fCurrTexture->ref();
- fCurrMaskFormat = glyph->fMaskFormat;
- }
-
- if (NULL == fVertices) {
- int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
- fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
- fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, fCurrMaskFormat);
- }
-
- SkRect r;
- r.fLeft = SkIntToScalar(x);
- r.fTop = SkIntToScalar(y);
- r.fRight = r.fLeft + SkIntToScalar(width);
- r.fBottom = r.fTop + SkIntToScalar(height);
-
- fVertexBounds.joinNonEmptyArg(r);
-
- int u0 = glyph->fAtlasLocation.fX;
- int v0 = glyph->fAtlasLocation.fY;
- int u1 = u0 + width;
- int v1 = v0 + height;
-
- size_t vertSize = get_vertex_stride(fCurrMaskFormat);
- intptr_t vertex = reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex;
-
- // V0
- SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fLeft, r.fTop);
- if (kA8_GrMaskFormat == fCurrMaskFormat) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize -
- sizeof(SkIPoint16));
- textureCoords->set(u0, v0);
- vertex += vertSize;
-
- // V1
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fLeft, r.fBottom);
- if (kA8_GrMaskFormat == fCurrMaskFormat) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(SkIPoint16));
- textureCoords->set(u0, v1);
- vertex += vertSize;
-
- // V2
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fRight, r.fBottom);
- if (kA8_GrMaskFormat == fCurrMaskFormat) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(SkIPoint16));
- textureCoords->set(u1, v1);
- vertex += vertSize;
-
- // V3
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fRight, r.fTop);
- if (kA8_GrMaskFormat == fCurrMaskFormat) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(SkIPoint16));
- textureCoords->set(u1, v0);
-
- fCurrVertex += 4;
-}
-
-void GrBitmapTextContext::flush() {
- if (NULL == fDrawTarget) {
- return;
- }
-
- if (fCurrVertex > 0) {
- GrPipelineBuilder pipelineBuilder;
- pipelineBuilder.setFromPaint(fPaint, fRenderTarget, fClip);
-
- // setup our sampler state for our text texture/atlas
- SkASSERT(SkIsAlign4(fCurrVertex));
- SkASSERT(fCurrTexture);
-
- SkASSERT(fStrike);
- GrColor color = fPaint.getColor();
- switch (fCurrMaskFormat) {
- // Color bitmap text
- case kARGB_GrMaskFormat: {
- int a = fSkPaint.getAlpha();
- color = SkColorSetARGB(a, a, a, a);
- break;
- }
- // LCD text
- case kA565_GrMaskFormat: {
- // TODO: move supportsRGBCoverage check to setupCoverageEffect and only add LCD
- // processor if the xp can support it. For now we will simply assume that if
- // fUseLCDText is true, then we have a known color output.
- const GrXPFactory* xpFactory = pipelineBuilder.getXPFactory();
- if (!xpFactory->supportsRGBCoverage(0, kRGBA_GrColorComponentFlags)) {
- SkDebugf("LCD Text will not draw correctly.\n");
- }
- break;
- }
- // Grayscale/BW text
- case kA8_GrMaskFormat:
- break;
- default:
- SkFAIL("Unexpected mask format.");
- }
-
- GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
- uint32_t textureUniqueID = fCurrTexture->getUniqueID();
- if (textureUniqueID != fEffectTextureUniqueID ||
- fCachedGeometryProcessor->color() != color ||
- !fCachedGeometryProcessor->localMatrix().cheapEqualTo(fLocalMatrix)) {
- // This will be ignored in the non A8 case
- bool opaqueVertexColors = GrColorIsOpaque(fPaint.getColor());
- fCachedGeometryProcessor.reset(GrBitmapTextGeoProc::Create(color,
- fCurrTexture,
- params,
- fCurrMaskFormat,
- opaqueVertexColors,
- fLocalMatrix));
- fEffectTextureUniqueID = textureUniqueID;
- }
-
- int nGlyphs = fCurrVertex / kVerticesPerGlyph;
- fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
- fDrawTarget->drawIndexedInstances(&pipelineBuilder,
- fCachedGeometryProcessor.get(),
- kTriangles_GrPrimitiveType,
- nGlyphs,
- kVerticesPerGlyph,
- kIndicesPerGlyph,
- &fVertexBounds);
-
- fDrawTarget->resetVertexSource();
- fVertices = NULL;
- fAllocVertexCount = 0;
- // reset to be those that are left
- fTotalVertexCount -= fCurrVertex;
- fCurrVertex = 0;
- fVertexBounds.setLargestInverted();
- SkSafeSetNull(fCurrTexture);
- }
-}
-
-inline void GrBitmapTextContext::finish() {
- this->flush();
- fTotalVertexCount = 0;
-
- GrTextContext::finish();
-}
diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h
deleted file mode 100644
index f843fc7..0000000
--- a/src/gpu/GrBitmapTextContext.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrBitmapTextContext_DEFINED
-#define GrBitmapTextContext_DEFINED
-
-#include "GrTextContext.h"
-
-#include "GrGeometryProcessor.h"
-
-class GrTextStrike;
-
-/*
- * This class implements GrTextContext using standard bitmap fonts
- */
-class GrBitmapTextContext : public GrTextContext {
-public:
- static GrBitmapTextContext* Create(GrContext*, SkGpuDevice*, const SkDeviceProperties&);
-
- virtual ~GrBitmapTextContext() {}
-
-private:
- GrTextStrike* fStrike;
- void* fVertices;
- int fCurrVertex;
- int fAllocVertexCount;
- int fTotalVertexCount;
- SkRect fVertexBounds;
- GrTexture* fCurrTexture;
- GrMaskFormat fCurrMaskFormat;
- SkAutoTUnref<const GrGeometryProcessor> fCachedGeometryProcessor;
- // Used to check whether fCachedEffect is still valid.
- uint32_t fEffectTextureUniqueID;
- SkMatrix fLocalMatrix;
-
- GrBitmapTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&);
-
- bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
- const SkPaint&, const SkMatrix& viewMatrix) override;
-
- void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
- const SkMatrix& viewMatrix, const char text[], size_t byteLength,
- SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
- void onDrawPosText(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) override;
-
- void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
- const SkIRect& regionClipBounds);
- void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
- bool uploadGlyph(GrGlyph*, GrFontScaler*);
- void flush(); // automatically called by destructor
- void finish();
-};
-
-#endif
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 4154005..7d315eb 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -15,10 +15,8 @@
#include "GrBatchTarget.h"
#include "GrBufferAllocPool.h"
#include "GrDefaultGeoProcFactory.h"
-#include "GrFontCache.h"
#include "GrGpuResource.h"
#include "GrGpuResourcePriv.h"
-#include "GrDistanceFieldTextContext.h"
#include "GrDrawTargetCaps.h"
#include "GrGpu.h"
#include "GrIndexBuffer.h"
@@ -98,7 +96,6 @@
fSoftwarePathRenderer = NULL;
fResourceCache = NULL;
fBatchFontCache = NULL;
- fFontCache = NULL;
fDrawBuffer = NULL;
fDrawBufferVBAllocPool = NULL;
fDrawBufferIBAllocPool = NULL;
@@ -123,8 +120,6 @@
fResourceCache = SkNEW(GrResourceCache);
fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
- fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
-
fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
fAARectRenderer = SkNEW_ARGS(GrAARectRenderer, (fGpu));
@@ -153,7 +148,6 @@
SkDELETE(fResourceCache);
SkDELETE(fBatchFontCache);
- SkDELETE(fFontCache);
SkDELETE(fDrawBuffer);
SkDELETE(fDrawBufferVBAllocPool);
SkDELETE(fDrawBufferIBAllocPool);
@@ -191,7 +185,6 @@
fOvalRenderer->reset();
fBatchFontCache->freeAll();
- fFontCache->freeAll();
fLayerCache->freeAll();
fTextBlobCache->freeAll();
}
@@ -211,7 +204,6 @@
fOvalRenderer->reset();
fBatchFontCache->freeAll();
- fFontCache->freeAll();
fLayerCache->freeAll();
// a path renderer may be holding onto resources
SkSafeSetNull(fPathRendererChain);
@@ -241,12 +233,7 @@
}
}
-#ifdef USE_BITMAP_TEXTBLOBS
return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDistanceFieldFonts);
-#else
- return GrDistanceFieldTextContext::Create(this, gpuDevice, leakyProperties,
- enableDistanceFieldFonts);
-#endif
}
////////////////////////////////////////////////////////////////////////////////
@@ -466,12 +453,6 @@
}
}
-#ifdef SK_DEVELOPER
-void GrContext::dumpFontCache() const {
- fFontCache->dump();
-}
-#endif
-
////////////////////////////////////////////////////////////////////////////////
static inline bool is_irect(const SkRect& r) {
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
deleted file mode 100755
index a5d11e6..0000000
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrDistanceFieldTextContext.h"
-#include "GrAtlas.h"
-#include "GrAtlasTextContext.h"
-#include "GrBitmapTextContext.h"
-#include "GrDrawTarget.h"
-#include "GrDrawTargetCaps.h"
-#include "GrFontAtlasSizes.h"
-#include "GrFontCache.h"
-#include "GrFontScaler.h"
-#include "GrGpu.h"
-#include "GrIndexBuffer.h"
-#include "GrStrokeInfo.h"
-#include "GrTexturePriv.h"
-
-#include "SkAutoKern.h"
-#include "SkColorFilter.h"
-#include "SkDistanceFieldGen.h"
-#include "SkDraw.h"
-#include "SkGlyphCache.h"
-#include "SkGpuDevice.h"
-#include "SkPath.h"
-#include "SkRTConf.h"
-#include "SkStrokeRec.h"
-#include "effects/GrDistanceFieldGeoProc.h"
-
-SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
- "Dump the contents of the font cache before every purge.");
-
-static const int kMinDFFontSize = 18;
-static const int kSmallDFFontSize = 32;
-static const int kSmallDFFontLimit = 32;
-static const int kMediumDFFontSize = 72;
-static const int kMediumDFFontLimit = 72;
-static const int kLargeDFFontSize = 162;
-
-static const int kVerticesPerGlyph = 4;
-static const int kIndicesPerGlyph = 6;
-
-#ifdef SK_DEBUG
-static const int kExpectedDistanceAdjustTableSize = 8;
-#endif
-static const int kDistanceAdjustLumShift = 5;
-
-GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
- SkGpuDevice* gpuDevice,
- const SkDeviceProperties& properties,
- bool enable)
- : GrTextContext(context, gpuDevice, properties) {
-#if SK_FORCE_DISTANCE_FIELD_TEXT
- fEnableDFRendering = true;
-#else
- fEnableDFRendering = enable;
-#endif
- fStrike = NULL;
- fDistanceAdjustTable = NULL;
-
- fEffectTextureUniqueID = SK_InvalidUniqueID;
- fEffectColor = GrColor_ILLEGAL;
- fEffectFlags = kInvalid_DistanceFieldEffectFlag;
-
- fVertices = NULL;
- fCurrVertex = 0;
- fAllocVertexCount = 0;
- fTotalVertexCount = 0;
- fCurrTexture = NULL;
-
- fVertexBounds.setLargestInverted();
-}
-
-GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* context,
- SkGpuDevice* gpuDevice,
- const SkDeviceProperties& props,
- bool enable) {
- GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextContext,
- (context, gpuDevice, props, enable));
- textContext->buildDistanceAdjustTable();
-#ifdef USE_BITMAP_TEXTBLOBS
- textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, gpuDevice, props,
- enable);
-#else
- textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpuDevice, props);
-#endif
-
- return textContext;
-}
-
-void GrDistanceFieldTextContext::buildDistanceAdjustTable() {
-
- // This is used for an approximation of the mask gamma hack, used by raster and bitmap
- // text. The mask gamma hack is based off of guessing what the blend color is going to
- // be, and adjusting the mask so that when run through the linear blend will
- // produce the value closest to the desired result. However, in practice this means
- // that the 'adjusted' mask is just increasing or decreasing the coverage of
- // the mask depending on what it is thought it will blit against. For black (on
- // assumed white) this means that coverages are decreased (on a curve). For white (on
- // assumed black) this means that coverages are increased (on a a curve). At
- // middle (perceptual) gray (which could be blit against anything) the coverages
- // remain the same.
- //
- // The idea here is that instead of determining the initial (real) coverage and
- // then adjusting that coverage, we determine an adjusted coverage directly by
- // essentially manipulating the geometry (in this case, the distance to the glyph
- // edge). So for black (on assumed white) this thins a bit; for white (on
- // assumed black) this fake bolds the geometry a bit.
- //
- // The distance adjustment is calculated by determining the actual coverage value which
- // when fed into in the mask gamma table gives us an 'adjusted coverage' value of 0.5. This
- // actual coverage value (assuming it's between 0 and 1) corresponds to a distance from the
- // actual edge. So by subtracting this distance adjustment and computing without the
- // the coverage adjustment we should get 0.5 coverage at the same point.
- //
- // This has several implications:
- // For non-gray lcd smoothed text, each subpixel essentially is using a
- // slightly different geometry.
- //
- // For black (on assumed white) this may not cover some pixels which were
- // previously covered; however those pixels would have been only slightly
- // covered and that slight coverage would have been decreased anyway. Also, some pixels
- // which were previously fully covered may no longer be fully covered.
- //
- // For white (on assumed black) this may cover some pixels which weren't
- // previously covered at all.
-
- int width, height;
- size_t size;
-
-#ifdef SK_GAMMA_CONTRAST
- SkScalar contrast = SK_GAMMA_CONTRAST;
-#else
- SkScalar contrast = 0.5f;
-#endif
- SkScalar paintGamma = fDeviceProperties.gamma();
- SkScalar deviceGamma = fDeviceProperties.gamma();
-
- size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
- &width, &height);
-
- SkASSERT(kExpectedDistanceAdjustTableSize == height);
- fDistanceAdjustTable = SkNEW_ARRAY(SkScalar, height);
-
- SkAutoTArray<uint8_t> data((int)size);
- SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get());
-
- // find the inverse points where we cross 0.5
- // binsearch might be better, but we only need to do this once on creation
- for (int row = 0; row < height; ++row) {
- uint8_t* rowPtr = data.get() + row*width;
- for (int col = 0; col < width - 1; ++col) {
- if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) {
- // compute point where a mask value will give us a result of 0.5
- float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPtr[col]);
- float borderAlpha = (col + interp) / 255.f;
-
- // compute t value for that alpha
- // this is an approximate inverse for smoothstep()
- float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5.0f) / 3.0f;
-
- // compute distance which gives us that t value
- const float kDistanceFieldAAFactor = 0.65f; // should match SK_DistanceFieldAAFactor
- float d = 2.0f*kDistanceFieldAAFactor*t - kDistanceFieldAAFactor;
-
- fDistanceAdjustTable[row] = d;
- break;
- }
- }
- }
-}
-
-
-GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
- SkDELETE_ARRAY(fDistanceAdjustTable);
- fDistanceAdjustTable = NULL;
-}
-
-bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix) {
- // TODO: support perspective (need getMaxScale replacement)
- if (viewMatrix.hasPerspective()) {
- return false;
- }
-
- SkScalar maxScale = viewMatrix.getMaxScale();
- SkScalar scaledTextSize = maxScale*skPaint.getTextSize();
- // Hinted text looks far better at small resolutions
- // Scaling up beyond 2x yields undesireable artifacts
- if (scaledTextSize < kMinDFFontSize || scaledTextSize > 2*kLargeDFFontSize) {
- return false;
- }
-
- if (!fEnableDFRendering && !skPaint.isDistanceFieldTextTEMP() &&
- scaledTextSize < kLargeDFFontSize) {
- return false;
- }
-
- // rasterizers and mask filters modify alpha, which doesn't
- // translate well to distance
- if (skPaint.getRasterizer() || skPaint.getMaskFilter() ||
- !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) {
- return false;
- }
-
- // TODO: add some stroking support
- if (skPaint.getStyle() != SkPaint::kFill_Style) {
- return false;
- }
-
- return true;
-}
-
-inline void GrDistanceFieldTextContext::init(GrRenderTarget* rt, const GrClip& clip,
- const GrPaint& paint, const SkPaint& skPaint,
- const SkIRect& regionClipBounds) {
- GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds);
-
- fStrike = NULL;
-
- const SkMatrix& ctm = fViewMatrix;
-
- // getMaxScale doesn't support perspective, so neither do we at the moment
- SkASSERT(!ctm.hasPerspective());
- SkScalar maxScale = ctm.getMaxScale();
- SkScalar textSize = fSkPaint.getTextSize();
- SkScalar scaledTextSize = textSize;
- // if we have non-unity scale, we need to choose our base text size
- // based on the SkPaint's text size multiplied by the max scale factor
- // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
- if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
- scaledTextSize *= maxScale;
- }
-
- fVertices = NULL;
- fCurrVertex = 0;
- fAllocVertexCount = 0;
- fTotalVertexCount = 0;
-
- if (scaledTextSize <= kSmallDFFontLimit) {
- fTextRatio = textSize / kSmallDFFontSize;
- fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
-#if DEBUG_TEXT_SIZE
- fSkPaint.setColor(SkColorSetARGB(0xFF, 0x00, 0x00, 0x7F));
- fPaint.setColor(GrColorPackRGBA(0x00, 0x00, 0x7F, 0xFF));
-#endif
- } else if (scaledTextSize <= kMediumDFFontLimit) {
- fTextRatio = textSize / kMediumDFFontSize;
- fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
-#if DEBUG_TEXT_SIZE
- fSkPaint.setColor(SkColorSetARGB(0xFF, 0x00, 0x3F, 0x00));
- fPaint.setColor(GrColorPackRGBA(0x00, 0x3F, 0x00, 0xFF));
-#endif
- } else {
- fTextRatio = textSize / kLargeDFFontSize;
- fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
-#if DEBUG_TEXT_SIZE
- fSkPaint.setColor(SkColorSetARGB(0xFF, 0x7F, 0x00, 0x00));
- fPaint.setColor(GrColorPackRGBA(0x7F, 0x00, 0x00, 0xFF));
-#endif
- }
-
- fUseLCDText = fSkPaint.isLCDRenderText();
-
- fSkPaint.setLCDRenderText(false);
- fSkPaint.setAutohinted(false);
- fSkPaint.setHinting(SkPaint::kNormal_Hinting);
- fSkPaint.setSubpixelText(true);
-}
-
-void GrDistanceFieldTextContext::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) {
- SkASSERT(byteLength == 0 || text != NULL);
-
- // nothing to draw
- if (text == NULL || byteLength == 0) {
- return;
- }
-
- fViewMatrix = viewMatrix;
- SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc();
- SkAutoGlyphCache autoCache(skPaint, &fDeviceProperties, NULL);
- SkGlyphCache* cache = autoCache.getCache();
-
- SkTArray<SkScalar> positions;
-
- const char* textPtr = text;
- SkFixed stopX = 0;
- SkFixed stopY = 0;
- SkFixed origin;
- switch (skPaint.getTextAlign()) {
- case SkPaint::kRight_Align: origin = SK_Fixed1; break;
- case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
- case SkPaint::kLeft_Align: origin = 0; break;
- default: SkFAIL("Invalid paint origin"); return;
- }
-
- SkAutoKern autokern;
- const char* stop = text + byteLength;
- while (textPtr < stop) {
- // don't need x, y here, since all subpixel variants will have the
- // same advance
- const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
-
- SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
- positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));
-
- SkFixed height = glyph.fAdvanceY;
- positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height)));
-
- stopX += width;
- stopY += height;
- }
- SkASSERT(textPtr == stop);
-
- // now adjust starting point depending on alignment
- SkScalar alignX = SkFixedToScalar(stopX);
- SkScalar alignY = SkFixedToScalar(stopY);
- if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
- alignX = SkScalarHalf(alignX);
- alignY = SkScalarHalf(alignY);
- } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
- alignX = 0;
- alignY = 0;
- }
- x -= alignX;
- y -= alignY;
- SkPoint offset = SkPoint::Make(x, y);
-
- this->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, positions.begin(),
- 2, offset, regionClipBounds);
-}
-
-void GrDistanceFieldTextContext::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) {
-
- SkASSERT(byteLength == 0 || text != NULL);
- SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
-
- // nothing to draw
- if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
- return;
- }
-
- fViewMatrix = viewMatrix;
- this->init(rt, clip, paint, skPaint, regionClipBounds);
-
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
-
- SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* fontScaler = GetGrFontScaler(cache);
-
- int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
- fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
-
- const char* stop = text + byteLength;
- SkTArray<char> fallbackTxt;
- SkTArray<SkScalar> fallbackPos;
-
- if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
- while (text < stop) {
- const char* lastText = text;
- // the last 2 parameters are ignored
- const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
-
- if (glyph.fWidth) {
- SkScalar x = offset.x() + pos[0];
- SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);
-
- if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kDistance_MaskStyle),
- x, y, fontScaler)) {
- // couldn't append, send to fallback
- fallbackTxt.push_back_n(SkToInt(text-lastText), lastText);
- fallbackPos.push_back(pos[0]);
- if (2 == scalarsPerPosition) {
- fallbackPos.push_back(pos[1]);
- }
- }
- }
- pos += scalarsPerPosition;
- }
- } else {
- SkScalar alignMul = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? SK_ScalarHalf
- : SK_Scalar1;
- while (text < stop) {
- const char* lastText = text;
- // the last 2 parameters are ignored
- const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
-
- if (glyph.fWidth) {
- SkScalar x = offset.x() + pos[0];
- SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);
-
- SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX)*alignMul*fTextRatio;
- SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY)*alignMul*fTextRatio;
-
- if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kDistance_MaskStyle),
- x - advanceX, y - advanceY, fontScaler)) {
- // couldn't append, send to fallback
- fallbackTxt.push_back_n(SkToInt(text-lastText), lastText);
- fallbackPos.push_back(pos[0]);
- if (2 == scalarsPerPosition) {
- fallbackPos.push_back(pos[1]);
- }
- }
- }
- pos += scalarsPerPosition;
- }
- }
-
- this->finish();
-
- if (fallbackTxt.count() > 0) {
- fFallbackTextContext->drawPosText(rt, clip, paint, skPaint, viewMatrix,
- fallbackTxt.begin(), fallbackTxt.count(),
- fallbackPos.begin(), scalarsPerPosition, offset,
- regionClipBounds);
- }
-}
-
-static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
- unsigned r = SkColorGetR(c);
- unsigned g = SkColorGetG(c);
- unsigned b = SkColorGetB(c);
- return GrColorPackRGBA(r, g, b, 0xff);
-}
-
-static size_t get_vertex_stride(bool useColorVerts) {
- return useColorVerts ? (sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16)) :
- (sizeof(SkPoint) + sizeof(SkIPoint16));
-}
-
-static void* alloc_vertices(GrDrawTarget* drawTarget,
- int numVertices,
- bool useColorVerts) {
- if (numVertices <= 0) {
- return NULL;
- }
-
- void* vertices = NULL;
- bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
- get_vertex_stride(useColorVerts),
- 0,
- &vertices,
- NULL);
- GrAlwaysAssert(success);
- return vertices;
-}
-
-void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
- GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
- GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
-
- uint32_t textureUniqueID = fCurrTexture->getUniqueID();
- const SkMatrix& ctm = fViewMatrix;
-
- // set up any flags
- uint32_t flags = 0;
- flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
- flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
- flags |= fUseLCDText && ctm.rectStaysRect() ?
- kRectToRect_DistanceFieldEffectFlag : 0;
- bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry());
- flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
-
- // see if we need to create a new effect
- if (textureUniqueID != fEffectTextureUniqueID ||
- filteredColor != fEffectColor ||
- flags != fEffectFlags ||
- !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) {
- GrColor color = fPaint.getColor();
-
- if (fUseLCDText) {
- GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
-
- float redCorrection =
- fDistanceAdjustTable[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift];
- float greenCorrection =
- fDistanceAdjustTable[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift];
- float blueCorrection =
- fDistanceAdjustTable[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift];
- GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
- GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrection,
- greenCorrection,
- blueCorrection);
- fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextGeoProc::Create(color,
- fViewMatrix,
- fCurrTexture,
- params,
- widthAdjust,
- flags));
- } else {
- flags |= kColorAttr_DistanceFieldEffectFlag;
- bool opaque = GrColorIsOpaque(color);
-#ifdef SK_GAMMA_APPLY_TO_A8
- U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.gamma(),
- filteredColor);
- float correction = fDistanceAdjustTable[lum >> kDistanceAdjustLumShift];
- fCachedGeometryProcessor.reset(GrDistanceFieldA8TextGeoProc::Create(color,
- fViewMatrix,
- fCurrTexture,
- params,
- correction,
- flags,
- opaque));
-#else
- fCachedGeometryProcessor.reset(GrDistanceFieldA8TextGeoProc::Create(color,
- fViewMatrix,
- fCurrTexture,
- params,
- flags,
- opaque));
-#endif
- }
- fEffectTextureUniqueID = textureUniqueID;
- fEffectColor = filteredColor;
- fEffectFlags = flags;
- }
-
-}
-
-inline bool GrDistanceFieldTextContext::uploadGlyph(GrGlyph* glyph, GrFontScaler* scaler) {
- if (!fStrike->glyphTooLargeForAtlas(glyph)) {
- if (fStrike->addGlyphToAtlas(glyph, scaler)) {
- return true;
- }
-
- // try to clear out an unused plot before we flush
- if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- return true;
- }
-
- if (c_DumpFontCache) {
-#ifdef SK_DEVELOPER
- fContext->getFontCache()->dump();
-#endif
- }
-
- // before we purge the cache, we must flush any accumulated draws
- this->flush();
- fContext->flush();
-
- // we should have an unused plot now
- if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- return true;
- }
-
- // we should never get here
- SkASSERT(false);
- }
-
- return false;
-}
-
-
-// Returns true if this method handled the glyph, false if needs to be passed to fallback
-//
-bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
- SkScalar sx, SkScalar sy,
- GrFontScaler* scaler) {
- if (NULL == fDrawTarget) {
- return true;
- }
-
- if (NULL == fStrike) {
- fStrike = fContext->getFontCache()->getStrike(scaler);
- }
-
- GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
- if (NULL == glyph || glyph->fBounds.isEmpty()) {
- return true;
- }
-
- // fallback to color glyph support
- if (kA8_GrMaskFormat != glyph->fMaskFormat) {
- return false;
- }
-
- SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
- SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
- SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
- SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
-
- SkScalar scale = fTextRatio;
- dx *= scale;
- dy *= scale;
- width *= scale;
- height *= scale;
- sx += dx;
- sy += dy;
- SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height);
-
- // check if we clipped out
- SkRect dstRect;
- const SkMatrix& ctm = fViewMatrix;
- (void) ctm.mapRect(&dstRect, glyphRect);
- if (fClipRect.quickReject(SkScalarTruncToInt(dstRect.left()),
- SkScalarTruncToInt(dstRect.top()),
- SkScalarTruncToInt(dstRect.right()),
- SkScalarTruncToInt(dstRect.bottom()))) {
- return true;
- }
-
- if (NULL == glyph->fPlot) {
- // needs to be a separate conditional to avoid over-optimization
- // on Nexus 7 and Nexus 10
-
- // If the glyph is too large we fall back to paths
- if (!uploadGlyph(glyph, scaler)) {
- if (NULL == glyph->fPath) {
- SkPath* path = SkNEW(SkPath);
- if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
- // flag the glyph as being dead?
- delete path;
- return true;
- }
- glyph->fPath = path;
- }
-
- // flush any accumulated draws before drawing this glyph as a path.
- this->flush();
-
- SkMatrix ctm;
- ctm.postTranslate(sx - dx, sy - dy);
-
- SkPath tmpPath(*glyph->fPath);
- tmpPath.transform(ctm);
-
- GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
- fContext->drawPath(fRenderTarget, fClip, fPaint, fViewMatrix, tmpPath, strokeInfo);
-
- // remove this glyph from the vertices we need to allocate
- fTotalVertexCount -= kVerticesPerGlyph;
- return true;
- }
- }
-
- SkASSERT(glyph->fPlot);
- GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
- glyph->fPlot->setDrawToken(drawToken);
-
- GrTexture* texture = glyph->fPlot->texture();
- SkASSERT(texture);
-
- if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fTotalVertexCount) {
- this->flush();
- fCurrTexture = texture;
- fCurrTexture->ref();
- }
-
- bool useColorVerts = !fUseLCDText;
-
- if (NULL == fVertices) {
- int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
- fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
- fVertices = alloc_vertices(fDrawTarget,
- fAllocVertexCount,
- useColorVerts);
- }
-
- fVertexBounds.joinNonEmptyArg(glyphRect);
-
- int u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
- int v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
- int u1 = u0 + glyph->fBounds.width() - 2*SK_DistanceFieldInset;
- int v1 = v0 + glyph->fBounds.height() - 2*SK_DistanceFieldInset;
-
- size_t vertSize = get_vertex_stride(useColorVerts);
- intptr_t vertex = reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex;
-
- // V0
- SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
- position->set(glyphRect.fLeft, glyphRect.fTop);
- if (useColorVerts) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize -
- sizeof(SkIPoint16));
- textureCoords->set(u0, v0);
- vertex += vertSize;
-
- // V1
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(glyphRect.fLeft, glyphRect.fBottom);
- if (useColorVerts) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(SkIPoint16));
- textureCoords->set(u0, v1);
- vertex += vertSize;
-
- // V2
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(glyphRect.fRight, glyphRect.fBottom);
- if (useColorVerts) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(SkIPoint16));
- textureCoords->set(u1, v1);
- vertex += vertSize;
-
- // V3
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(glyphRect.fRight, glyphRect.fTop);
- if (useColorVerts) {
- SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *color = fPaint.getColor();
- }
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(SkIPoint16));
- textureCoords->set(u1, v0);
-
- fCurrVertex += 4;
-
- return true;
-}
-
-void GrDistanceFieldTextContext::flush() {
- if (NULL == fDrawTarget) {
- return;
- }
-
- if (fCurrVertex > 0) {
- GrPipelineBuilder pipelineBuilder;
- pipelineBuilder.setFromPaint(fPaint, fRenderTarget, fClip);
-
- // setup our sampler state for our text texture/atlas
- SkASSERT(SkIsAlign4(fCurrVertex));
-
- // get our current color
- SkColor filteredColor;
- SkColorFilter* colorFilter = fSkPaint.getColorFilter();
- if (colorFilter) {
- filteredColor = colorFilter->filterColor(fSkPaint.getColor());
- } else {
- filteredColor = fSkPaint.getColor();
- }
- this->setupCoverageEffect(filteredColor);
-
- // Set draw state
- if (fUseLCDText) {
- // TODO: move supportsRGBCoverage check to setupCoverageEffect and only add LCD
- // processor if the xp can support it. For now we will simply assume that if
- // fUseLCDText is true, then we have a known color output.
- const GrXPFactory* xpFactory = pipelineBuilder.getXPFactory();
- if (!xpFactory->supportsRGBCoverage(0, kRGBA_GrColorComponentFlags)) {
- SkDebugf("LCD Text will not draw correctly.\n");
- }
- SkASSERT(!fCachedGeometryProcessor->hasVertexColor());
- } else {
- // We're using per-vertex color.
- SkASSERT(fCachedGeometryProcessor->hasVertexColor());
- }
- int nGlyphs = fCurrVertex / kVerticesPerGlyph;
- fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
- fDrawTarget->drawIndexedInstances(&pipelineBuilder,
- fCachedGeometryProcessor.get(),
- kTriangles_GrPrimitiveType,
- nGlyphs,
- kVerticesPerGlyph,
- kIndicesPerGlyph,
- &fVertexBounds);
- fDrawTarget->resetVertexSource();
- fVertices = NULL;
- fTotalVertexCount -= fCurrVertex;
- fCurrVertex = 0;
- SkSafeSetNull(fCurrTexture);
- fVertexBounds.setLargestInverted();
- }
-}
-
-inline void GrDistanceFieldTextContext::finish() {
- this->flush();
- fTotalVertexCount = 0;
-
- GrTextContext::finish();
-}
-
diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h
deleted file mode 100644
index 1524a94..0000000
--- a/src/gpu/GrDistanceFieldTextContext.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrDistanceFieldTextContext_DEFINED
-#define GrDistanceFieldTextContext_DEFINED
-
-#include "GrTextContext.h"
-
-class GrGeometryProcessor;
-class GrTextStrike;
-
-/*
- * This class implements GrTextContext using distance field fonts
- */
-class GrDistanceFieldTextContext : public GrTextContext {
-public:
- static GrDistanceFieldTextContext* Create(GrContext*, SkGpuDevice*, const SkDeviceProperties&,
- bool enable);
-
- virtual ~GrDistanceFieldTextContext();
-
-private:
- enum {
- kMinRequestedGlyphs = 1,
- kDefaultRequestedGlyphs = 64,
- kMinRequestedVerts = kMinRequestedGlyphs * 4,
- kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
- };
-
- GrTextStrike* fStrike;
- SkScalar fTextRatio;
- bool fUseLCDText;
- bool fEnableDFRendering;
- SkAutoTUnref<GrGeometryProcessor> fCachedGeometryProcessor;
- SkScalar* fDistanceAdjustTable;
- // Used to check whether fCachedEffect is still valid.
- uint32_t fEffectTextureUniqueID;
- SkColor fEffectColor;
- uint32_t fEffectFlags;
- void* fVertices;
- int fCurrVertex;
- int fAllocVertexCount;
- int fTotalVertexCount;
- GrTexture* fCurrTexture;
- SkRect fVertexBounds;
- SkMatrix fViewMatrix;
-
- GrDistanceFieldTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&, bool enable);
- void buildDistanceAdjustTable();
-
- bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
- const SkPaint&, const SkMatrix& viewMatrix) override;
-
- void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
- const SkMatrix& viewMatrix,
- const char text[], size_t byteLength,
- SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
- void onDrawPosText(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) override;
-
- void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
- const SkIRect& regionClipBounds);
- bool appendGlyph(GrGlyph::PackedID, SkScalar left, SkScalar top, GrFontScaler*);
- bool uploadGlyph(GrGlyph*, GrFontScaler*);
- void setupCoverageEffect(const SkColor& filteredColor);
- void flush(); // automatically called by destructor
- void finish();
-};
-
-#endif
diff --git a/src/gpu/GrFlushToGpuDrawTarget.cpp b/src/gpu/GrFlushToGpuDrawTarget.cpp
index 23fa310..1ccb25d 100644
--- a/src/gpu/GrFlushToGpuDrawTarget.cpp
+++ b/src/gpu/GrFlushToGpuDrawTarget.cpp
@@ -7,7 +7,6 @@
#include "GrFlushToGpuDrawTarget.h"
#include "GrContext.h"
-#include "GrFontCache.h"
#include "GrGpu.h"
#include "GrBufferAllocPool.h"
@@ -86,8 +85,6 @@
}
fFlushing = true;
- fGpu->getContext()->getFontCache()->updateTextures();
-
fGpu->saveActiveTraceMarkers();
this->onFlush();
diff --git a/src/gpu/GrFontCache.cpp b/src/gpu/GrFontCache.cpp
deleted file mode 100644
index 5952366..0000000
--- a/src/gpu/GrFontCache.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrFontCache.h"
-#include "GrFontAtlasSizes.h"
-#include "GrGpu.h"
-#include "GrRectanizer.h"
-#include "GrSurfacePriv.h"
-#include "SkString.h"
-
-#include "SkDistanceFieldGen.h"
-
-///////////////////////////////////////////////////////////////////////////////
-
-#define FONT_CACHE_STATS 0
-#if FONT_CACHE_STATS
-static int g_PurgeCount = 0;
-#endif
-
-GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
- gpu->ref();
- for (int i = 0; i < kAtlasCount; ++i) {
- fAtlases[i] = NULL;
- }
-
- fHead = fTail = NULL;
-}
-
-GrFontCache::~GrFontCache() {
- SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache);
- while (!iter.done()) {
- SkDELETE(&(*iter));
- ++iter;
- }
- for (int i = 0; i < kAtlasCount; ++i) {
- delete fAtlases[i];
- }
- fGpu->unref();
-#if FONT_CACHE_STATS
- SkDebugf("Num purges: %d\n", g_PurgeCount);
-#endif
-}
-
-static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
- static const GrPixelConfig sPixelConfigs[] = {
- kAlpha_8_GrPixelConfig,
- kRGB_565_GrPixelConfig,
- kSkia8888_GrPixelConfig
- };
- SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sPixelConfigs) == kMaskFormatCount, array_size_mismatch);
-
- return sPixelConfigs[format];
-}
-
-static int mask_format_to_atlas_index(GrMaskFormat format) {
- static const int sAtlasIndices[] = {
- GrFontCache::kA8_AtlasType,
- GrFontCache::k565_AtlasType,
- GrFontCache::k8888_AtlasType
- };
- SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_size_mismatch);
-
- SkASSERT(sAtlasIndices[format] < GrFontCache::kAtlasCount);
- return sAtlasIndices[format];
-}
-
-GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler) {
- GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, (this, scaler->getKey()));
- fCache.add(strike);
-
- if (fHead) {
- fHead->fPrev = strike;
- } else {
- SkASSERT(NULL == fTail);
- fTail = strike;
- }
- strike->fPrev = NULL;
- strike->fNext = fHead;
- fHead = strike;
-
- return strike;
-}
-
-void GrFontCache::freeAll() {
- SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache);
- while (!iter.done()) {
- SkDELETE(&(*iter));
- ++iter;
- }
- fCache.rewind();
- for (int i = 0; i < kAtlasCount; ++i) {
- delete fAtlases[i];
- fAtlases[i] = NULL;
- }
- fHead = NULL;
- fTail = NULL;
-}
-
-void GrFontCache::purgeStrike(GrTextStrike* strike) {
- fCache.remove(*(strike->fFontScalerKey));
- this->detachStrikeFromList(strike);
- delete strike;
-}
-
-
-GrPlot* GrFontCache::addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* usage,
- int width, int height, const void* image,
- SkIPoint16* loc) {
- GrPixelConfig config = mask_format_to_pixel_config(format);
- int atlasIndex = mask_format_to_atlas_index(format);
- if (NULL == fAtlases[atlasIndex]) {
- if (kA8_GrMaskFormat == format) {
- SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_A8_TEXTURE_WIDTH,
- GR_FONT_ATLAS_TEXTURE_HEIGHT);
- fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSurfaceFlags,
- textureSize,
- GR_FONT_ATLAS_A8_NUM_PLOTS_X,
- GR_FONT_ATLAS_NUM_PLOTS_Y,
- true));
- } else {
- SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_TEXTURE_WIDTH,
- GR_FONT_ATLAS_TEXTURE_HEIGHT);
- fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSurfaceFlags,
- textureSize,
- GR_FONT_ATLAS_NUM_PLOTS_X,
- GR_FONT_ATLAS_NUM_PLOTS_Y,
- true));
- }
- }
- return fAtlases[atlasIndex]->addToAtlas(usage, width, height, image, loc);
-}
-
-
-bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph) {
- SkASSERT(preserveStrike);
-
- int index = mask_format_to_atlas_index(glyph->fMaskFormat);
- GrAtlas* atlas = fAtlases[index];
- GrPlot* plot = atlas->getUnusedPlot();
- if (NULL == plot) {
- return false;
- }
- plot->resetRects();
-
- GrTextStrike* strike = fHead;
- while (strike) {
- GrTextStrike* strikeToPurge = strike;
- strike = strikeToPurge->fNext;
- strikeToPurge->removePlot(plot);
-
- // clear out any empty strikes (except this one)
- if (strikeToPurge != preserveStrike && strikeToPurge->fPlotUsage.isEmpty()) {
- this->purgeStrike(strikeToPurge);
- }
- }
-
-#if FONT_CACHE_STATS
- ++g_PurgeCount;
-#endif
-
- return true;
-}
-
-#ifdef SK_DEBUG
-void GrFontCache::validate() const {
- int count = fCache.count();
- if (0 == count) {
- SkASSERT(!fHead);
- SkASSERT(!fTail);
- } else if (1 == count) {
- SkASSERT(fHead == fTail);
- } else {
- SkASSERT(fHead != fTail);
- }
-
- int count2 = 0;
- const GrTextStrike* strike = fHead;
- while (strike) {
- count2 += 1;
- strike = strike->fNext;
- }
- SkASSERT(count == count2);
-
- count2 = 0;
- strike = fTail;
- while (strike) {
- count2 += 1;
- strike = strike->fPrev;
- }
- SkASSERT(count == count2);
-}
-#endif
-
-void GrFontCache::dump() const {
- static int gDumpCount = 0;
- for (int i = 0; i < kAtlasCount; ++i) {
- if (fAtlases[i]) {
- GrTexture* texture = fAtlases[i]->getTexture();
- if (texture) {
- SkString filename;
-#ifdef SK_BUILD_FOR_ANDROID
- filename.printf("/sdcard/fontcache_%d%d.png", gDumpCount, i);
-#else
- filename.printf("fontcache_%d%d.png", gDumpCount, i);
-#endif
- texture->surfacePriv().savePixels(filename.c_str());
- }
- }
- }
- ++gDumpCount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
- static int gCounter;
-#endif
-
-/*
- The text strike is specific to a given font/style/matrix setup, which is
- represented by the GrHostFontScaler object we are given in getGlyph().
-
- We map a 32bit glyphID to a GrGlyph record, which in turn points to a
- atlas and a position within that texture.
- */
-
-GrTextStrike::GrTextStrike(GrFontCache* cache, const GrFontDescKey* key)
- : fPool(9/*start allocations at 512 bytes*/) {
- fFontScalerKey = key;
- fFontScalerKey->ref();
-
- fFontCache = cache; // no need to ref, it won't go away before we do
-
-#ifdef SK_DEBUG
-// SkDebugf(" GrTextStrike %p %d\n", this, gCounter);
- gCounter += 1;
-#endif
-}
-
-GrTextStrike::~GrTextStrike() {
- fFontScalerKey->unref();
- SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
- while (!iter.done()) {
- (*iter).free();
- ++iter;
- }
-
-#ifdef SK_DEBUG
- gCounter -= 1;
-// SkDebugf("~GrTextStrike %p %d\n", this, gCounter);
-#endif
-}
-
-GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
- GrFontScaler* scaler) {
- SkIRect bounds;
- if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(packed)) {
- if (!scaler->getPackedGlyphDFBounds(packed, &bounds)) {
- return NULL;
- }
- } else {
- if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
- return NULL;
- }
- }
- GrMaskFormat format = scaler->getPackedGlyphMaskFormat(packed);
-
- GrGlyph* glyph = (GrGlyph*)fPool.alloc(sizeof(GrGlyph), SK_MALLOC_THROW);
- glyph->init(packed, bounds, format);
- fCache.add(glyph);
- return glyph;
-}
-
-void GrTextStrike::removePlot(const GrPlot* plot) {
- SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
- while (!iter.done()) {
- if (plot == (*iter).fPlot) {
- (*iter).fPlot = NULL;
- }
- ++iter;
- }
-
- GrAtlas::RemovePlot(&fPlotUsage, plot);
-}
-
-bool GrTextStrike::glyphTooLargeForAtlas(GrGlyph* glyph) {
- int width = glyph->fBounds.width();
- int height = glyph->fBounds.height();
- bool useDistanceField =
- (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID));
- int pad = useDistanceField ? 2 * SK_DistanceFieldPad : 0;
- int plotWidth = (kA8_GrMaskFormat == glyph->fMaskFormat) ? GR_FONT_ATLAS_A8_PLOT_WIDTH
- : GR_FONT_ATLAS_PLOT_WIDTH;
- if (width + pad > plotWidth) {
- return true;
- }
- if (height + pad > GR_FONT_ATLAS_PLOT_HEIGHT) {
- return true;
- }
-
- return false;
-}
-
-bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
-#if 0 // testing hack to force us to flush our cache often
- static int gCounter;
- if ((++gCounter % 10) == 0) return false;
-#endif
-
- SkASSERT(glyph);
- SkASSERT(scaler);
- SkASSERT(fCache.find(glyph->fPackedID));
- SkASSERT(NULL == glyph->fPlot);
-
- SkAutoUnref ar(SkSafeRef(scaler));
-
- int bytesPerPixel = GrMaskFormatBytesPerPixel(glyph->fMaskFormat);
-
- size_t size = glyph->fBounds.area() * bytesPerPixel;
- GrAutoMalloc<1024> storage(size);
-
- if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID)) {
- if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(),
- glyph->height(),
- storage.get())) {
- return false;
- }
- } else {
- if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
- glyph->height(),
- glyph->width() * bytesPerPixel,
- storage.get())) {
- return false;
- }
- }
-
- GrPlot* plot = fFontCache->addToAtlas(glyph->fMaskFormat, &fPlotUsage,
- glyph->width(), glyph->height(),
- storage.get(), &glyph->fAtlasLocation);
-
- if (NULL == plot) {
- return false;
- }
-
- glyph->fPlot = plot;
- return true;
-}
diff --git a/src/gpu/GrFontCache.h b/src/gpu/GrFontCache.h
deleted file mode 100644
index 31e5601..0000000
--- a/src/gpu/GrFontCache.h
+++ /dev/null
@@ -1,181 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#ifndef GrTextStrike_DEFINED
-#define GrTextStrike_DEFINED
-
-#include "GrAtlas.h"
-#include "GrDrawTarget.h"
-#include "GrFontScaler.h"
-#include "GrGlyph.h"
-#include "SkTDynamicHash.h"
-#include "SkVarAlloc.h"
-
-class GrFontCache;
-class GrGpu;
-class GrFontPurgeListener;
-
-/**
- * The textstrike maps a hostfontscaler instance to a dictionary of
- * glyphid->strike
- */
-class GrTextStrike {
-public:
- GrTextStrike(GrFontCache*, const GrFontDescKey* fontScalerKey);
- ~GrTextStrike();
-
- const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
- GrFontCache* getFontCache() const { return fFontCache; }
-
- inline GrGlyph* getGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler) {
- GrGlyph* glyph = fCache.find(packed);
- if (NULL == glyph) {
- glyph = this->generateGlyph(packed, scaler);
- }
- return glyph;
- }
-
- // returns true if glyph (or glyph+padding for distance field)
- // is too large to ever fit in texture atlas subregions (GrPlots)
- bool glyphTooLargeForAtlas(GrGlyph*);
- // returns true if glyph successfully added to texture atlas, false otherwise
- bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
-
- // testing
- int countGlyphs() const { return fCache.count(); }
-
- // remove any references to this plot
- void removePlot(const GrPlot* plot);
-
- static const GrFontDescKey& GetKey(const GrTextStrike& ts) {
- return *(ts.fFontScalerKey);
- }
- static uint32_t Hash(const GrFontDescKey& key) {
- return key.getHash();
- }
-
-public:
- // for easy removal from list
- GrTextStrike* fPrev;
- GrTextStrike* fNext;
-
-private:
- SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
- const GrFontDescKey* fFontScalerKey;
- SkVarAlloc fPool;
-
- GrFontCache* fFontCache;
-
- GrAtlas::ClientPlotUsage fPlotUsage;
-
- GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
-
- friend class GrFontCache;
-};
-
-class GrFontCache {
-public:
- GrFontCache(GrGpu*);
- ~GrFontCache();
-
- inline GrTextStrike* getStrike(GrFontScaler* scaler) {
- this->validate();
-
- GrTextStrike* strike = fCache.find(*(scaler->getKey()));
- if (NULL == strike) {
- strike = this->generateStrike(scaler);
- } else if (strike->fPrev) {
- // Need to put the strike at the head of its dllist, since that is how
- // we age the strikes for purging (we purge from the back of the list)
- this->detachStrikeFromList(strike);
- // attach at the head
- fHead->fPrev = strike;
- strike->fNext = fHead;
- strike->fPrev = NULL;
- fHead = strike;
- }
- this->validate();
- return strike;
- }
-
- // add to texture atlas that matches this format
- GrPlot* addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* usage,
- int width, int height, const void* image,
- SkIPoint16* loc);
-
- void freeAll();
-
- // make an unused plot available for this glyph
- bool freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph);
-
- // testing
- int countStrikes() const { return fCache.count(); }
- GrTextStrike* getHeadStrike() const { return fHead; }
-
- void updateTextures() {
- for (int i = 0; i < kAtlasCount; ++i) {
- if (fAtlases[i]) {
- fAtlases[i]->uploadPlotsToTexture();
- }
- }
- }
-
-#ifdef SK_DEBUG
- void validate() const;
-#else
- void validate() const {}
-#endif
-
- void dump() const;
-
- enum AtlasType {
- kA8_AtlasType, //!< 1-byte per pixel
- k565_AtlasType, //!< 2-bytes per pixel
- k8888_AtlasType, //!< 4-bytes per pixel
-
- kLast_AtlasType = k8888_AtlasType
- };
- static const int kAtlasCount = kLast_AtlasType + 1;
-
-private:
- friend class GrFontPurgeListener;
-
- SkTDynamicHash<GrTextStrike, GrFontDescKey> fCache;
- // for LRU
- GrTextStrike* fHead;
- GrTextStrike* fTail;
-
- GrGpu* fGpu;
- GrAtlas* fAtlases[kAtlasCount];
-
- GrTextStrike* generateStrike(GrFontScaler*);
-
- inline void detachStrikeFromList(GrTextStrike* strike) {
- if (strike->fPrev) {
- SkASSERT(fHead != strike);
- strike->fPrev->fNext = strike->fNext;
- } else {
- SkASSERT(fHead == strike);
- fHead = strike->fNext;
- }
-
- if (strike->fNext) {
- SkASSERT(fTail != strike);
- strike->fNext->fPrev = strike->fPrev;
- } else {
- SkASSERT(fTail == strike);
- fTail = strike->fPrev;
- }
- }
-
- void purgeStrike(GrTextStrike* strike);
-};
-
-#endif
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 330f79d..0d64915 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -7,7 +7,6 @@
#include "GrStencilAndCoverTextContext.h"
#include "GrAtlasTextContext.h"
-#include "GrBitmapTextContext.h"
#include "GrDrawTarget.h"
#include "GrGpu.h"
#include "GrPath.h"
@@ -35,12 +34,8 @@
const SkDeviceProperties& props) {
GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverTextContext,
(context, gpuDevice, props));
-#ifdef USE_BITMAP_TEXTBLOBS
textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, gpuDevice, props,
false);
-#else
- textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpuDevice, props);
-#endif
return textContext;
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 337f400..0decb32 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -7,14 +7,13 @@
#include "SkGpuDevice.h"
-#include "GrBitmapTextContext.h"
#include "GrContext.h"
-#include "GrDistanceFieldTextContext.h"
#include "GrGpu.h"
#include "GrGpuResourcePriv.h"
#include "GrLayerHoister.h"
#include "GrRecordReplaceDraw.h"
#include "GrStrokeInfo.h"
+#include "GrTextContext.h"
#include "GrTracing.h"
#include "SkCanvasPriv.h"
#include "SkDeviceImageFilterProxy.h"