Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Unified Diff: src/gpu/GrDistanceFieldTextContext.cpp

Issue 1104343003: remove old text contexts and fontcache (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweak Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrDistanceFieldTextContext.h ('k') | src/gpu/GrFlushToGpuDrawTarget.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrDistanceFieldTextContext.cpp
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
deleted file mode 100755
index a5d11e6fb9fbc4afc5f1dcf653e90672b9ff41db..0000000000000000000000000000000000000000
--- 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();
-}
-
« no previous file with comments | « src/gpu/GrDistanceFieldTextContext.h ('k') | src/gpu/GrFlushToGpuDrawTarget.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698