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

Unified Diff: src/gpu/GrStencilAndCoverTextContext.cpp

Issue 1521453002: Move all text stuff to its own folder (Closed) Base URL: https://skia.googlesource.com/skia.git@cleanuptext11textutils2
Patch Set: Created 5 years 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/GrStencilAndCoverTextContext.h ('k') | src/gpu/GrTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrStencilAndCoverTextContext.cpp
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
deleted file mode 100644
index d28f1a803a0abe7df26843e7848fd21821d8b4f5..0000000000000000000000000000000000000000
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrStencilAndCoverTextContext.h"
-#include "GrAtlasTextContext.h"
-#include "GrDrawContext.h"
-#include "GrDrawTarget.h"
-#include "GrPath.h"
-#include "GrPathRange.h"
-#include "GrResourceProvider.h"
-#include "SkAutoKern.h"
-#include "SkDraw.h"
-#include "SkDrawProcs.h"
-#include "SkGlyphCache.h"
-#include "SkGpuDevice.h"
-#include "SkGrPriv.h"
-#include "SkPath.h"
-#include "SkTextBlobRunIterator.h"
-#include "SkTextMapStateProc.h"
-#include "SkTextFormatParams.h"
-
-#include "batches/GrDrawPathBatch.h"
-
-template<typename Key, typename Val> static void delete_hash_map_entry(const Key&, Val* val) {
- SkASSERT(*val);
- delete *val;
-}
-
-template<typename T> static void delete_hash_table_entry(T* val) {
- SkASSERT(*val);
- delete *val;
-}
-
-GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
- const SkSurfaceProps& surfaceProps)
- : INHERITED(context, surfaceProps),
- fCacheSize(0) {
-}
-
-GrStencilAndCoverTextContext*
-GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& surfaceProps) {
- GrStencilAndCoverTextContext* textContext =
- new GrStencilAndCoverTextContext(context, surfaceProps);
- textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, surfaceProps);
-
- return textContext;
-}
-
-GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
- fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>);
- fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>);
-}
-
-bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) {
- if (skPaint.getRasterizer()) {
- return false;
- }
- if (skPaint.getMaskFilter()) {
- return false;
- }
- if (SkPathEffect* pe = skPaint.getPathEffect()) {
- if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) {
- return false;
- }
- }
- // No hairlines. They would require new paths with customized strokes for every new draw matrix.
- return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth();
-}
-
-void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix,
- const char text[],
- size_t byteLength,
- SkScalar x, SkScalar y,
- const SkIRect& clipBounds) {
- TextRun run(skPaint);
- GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
- run.setText(text, byteLength, x, y);
- run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
- fFallbackTextContext, skPaint);
-}
-
-void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc,
- 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& clipBounds) {
- TextRun run(skPaint);
- GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
- run.setPosText(text, byteLength, pos, scalarsPerPosition, offset);
- run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
- fFallbackTextContext, skPaint);
-}
-
-void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc,
- const GrClip& clip, const SkPaint& skPaint,
- const SkMatrix& viewMatrix,
- const SkTextBlob* skBlob, SkScalar x, SkScalar y,
- SkDrawFilter* drawFilter,
- const SkIRect& clipBounds) {
- if (!this->internalCanDraw(skPaint)) {
- fFallbackTextContext->drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob, x, y,
- drawFilter, clipBounds);
- return;
- }
-
- if (drawFilter || skPaint.getPathEffect()) {
- // This draw can't be cached.
- INHERITED::drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob, x, y, drawFilter,
- clipBounds);
- return;
- }
-
- if (fContext->abandoned()) {
- return;
- }
-
- GrPaint paint;
- if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) {
- return;
- }
-
- const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);
- GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
-
- TextBlob::Iter iter(blob);
- for (TextRun* run = iter.get(); run; run = iter.next()) {
- run->draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, x, y, clipBounds,
- fFallbackTextContext, skPaint);
- run->releaseGlyphCache();
- }
-}
-
-const GrStencilAndCoverTextContext::TextBlob&
-GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob,
- const SkPaint& skPaint) {
- // The font-related parameters are baked into the text blob and will override this skPaint, so
- // the only remaining properties that can affect a TextBlob are the ones related to stroke.
- if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path.
- if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) {
- fLRUList.remove(*found);
- fLRUList.addToTail(*found);
- return **found;
- }
- TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint);
- this->purgeToFit(*blob);
- fBlobIdCache.set(skBlob->uniqueID(), blob);
- fLRUList.addToTail(blob);
- fCacheSize += blob->cpuMemorySize();
- return *blob;
- } else {
- GrStrokeInfo stroke(skPaint);
- SkSTArray<4, uint32_t, true> key;
- key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt());
- key[0] = skBlob->uniqueID();
- stroke.asUniqueKeyFragment(&key[1]);
- if (TextBlob** found = fBlobKeyCache.find(key)) {
- fLRUList.remove(*found);
- fLRUList.addToTail(*found);
- return **found;
- }
- TextBlob* blob = new TextBlob(key, skBlob, skPaint);
- this->purgeToFit(*blob);
- fBlobKeyCache.set(blob);
- fLRUList.addToTail(blob);
- fCacheSize += blob->cpuMemorySize();
- return *blob;
- }
-}
-
-void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) {
- static const size_t maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for caching text blobs.
-
- size_t maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize();
- while (fCacheSize && fCacheSize > maxSizeForNewBlob) {
- TextBlob* lru = fLRUList.head();
- if (1 == lru->key().count()) {
- // 1-length keys are unterstood to be the blob id.
- fBlobIdCache.remove(lru->key()[0]);
- } else {
- fBlobKeyCache.remove(lru->key());
- }
- fLRUList.remove(lru);
- fCacheSize -= lru->cpuMemorySize();
- delete lru;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob,
- const SkPaint& skPaint) {
- fCpuMemorySize = sizeof(TextBlob);
- SkPaint runPaint(skPaint);
- for (SkTextBlobRunIterator iter(skBlob); !iter.done(); iter.next()) {
- iter.applyFontToPaint(&runPaint); // No need to re-seed the paint.
- TextRun* run = this->addToTail(runPaint);
-
- const char* text = reinterpret_cast<const char*>(iter.glyphs());
- size_t byteLength = sizeof(uint16_t) * iter.glyphCount();
- const SkPoint& runOffset = iter.offset();
-
- switch (iter.positioning()) {
- case SkTextBlob::kDefault_Positioning:
- run->setText(text, byteLength, runOffset.fX, runOffset.fY);
- break;
- case SkTextBlob::kHorizontal_Positioning:
- run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0, runOffset.fY));
- break;
- case SkTextBlob::kFull_Positioning:
- run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0, 0));
- break;
- }
-
- fCpuMemorySize += run->computeSizeInCache();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-class GrStencilAndCoverTextContext::FallbackBlobBuilder {
-public:
- FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {}
-
- bool isInitialized() const { return SkToBool(fBuilder); }
-
- void init(const SkPaint& font, SkScalar textRatio);
-
- void appendGlyph(uint16_t glyphId, const SkPoint& pos);
-
- const SkTextBlob* buildIfNeeded(int* count);
-
-private:
- enum { kWriteBufferSize = 1024 };
-
- void flush();
-
- SkAutoTDelete<SkTextBlobBuilder> fBuilder;
- SkPaint fFont;
- int fBuffIdx;
- int fCount;
- uint16_t fGlyphIds[kWriteBufferSize];
- SkPoint fPositions[kWriteBufferSize];
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
- : fStroke(fontAndStroke),
- fFont(fontAndStroke),
- fTotalGlyphCount(0),
- fFallbackGlyphCount(0),
- fDetachedGlyphCache(nullptr),
- fLastDrawnGlyphsID(SK_InvalidUniqueID) {
- SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
-
- // Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
- // rendering API for stroking).
- fFont.setStyle(SkPaint::kFill_Style);
-
- if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
- // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke.
- SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(),
- kStdFakeBoldInterpKeys,
- kStdFakeBoldInterpValues,
- kStdFakeBoldInterpLength);
- SkScalar extra = SkScalarMul(fFont.getTextSize(), fakeBoldScale);
- fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
- true /*strokeAndFill*/);
-
- fFont.setFakeBoldText(false);
- }
-
- if (!fFont.getPathEffect() && !fStroke.isDashed()) {
- // We can draw the glyphs from canonically sized paths.
- fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
- fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize();
-
- // Compensate for the glyphs being scaled by fTextRatio.
- if (!fStroke.isFillStyle()) {
- fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
- SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
- }
-
- fFont.setLinearText(true);
- fFont.setLCDRenderText(false);
- fFont.setAutohinted(false);
- fFont.setHinting(SkPaint::kNo_Hinting);
- fFont.setSubpixelText(true);
- fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
-
- fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() &&
- 0 == fFont.getTextSkewX() &&
- !fFont.isFakeBoldText() &&
- !fFont.isVerticalText();
- } else {
- fTextRatio = fTextInverseRatio = 1.0f;
- fUsingRawGlyphPaths = false;
- }
-
- // Generate the key that will be used to cache the GPU glyph path objects.
- if (fUsingRawGlyphPaths && fStroke.isFillStyle()) {
- static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::GenerateDomain();
-
- const SkTypeface* typeface = fFont.getTypeface();
- GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1);
- reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
- } else {
- static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain();
-
- int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt();
- if (fUsingRawGlyphPaths) {
- const SkTypeface* typeface = fFont.getTypeface();
- GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + strokeDataCount);
- reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
- reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount;
- fStroke.asUniqueKeyFragment(&builder[2]);
- } else {
- SkGlyphCache* glyphCache = this->getGlyphCache();
- const SkTypeface* typeface = glyphCache->getScalerContext()->getTypeface();
- const SkDescriptor* desc = &glyphCache->getDescriptor();
- int descDataCount = (desc->getLength() + 3) / 4;
- GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain,
- 2 + strokeDataCount + descDataCount);
- reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
- reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount | (descDataCount << 16);
- fStroke.asUniqueKeyFragment(&builder[2]);
- memcpy(&builder[2 + strokeDataCount], desc, desc->getLength());
- }
- }
-}
-
-GrStencilAndCoverTextContext::TextRun::~TextRun() {
- this->releaseGlyphCache();
-}
-
-void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t byteLength,
- SkScalar x, SkScalar y) {
- SkASSERT(byteLength == 0 || text != nullptr);
-
- SkGlyphCache* glyphCache = this->getGlyphCache();
- SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
-
- fTotalGlyphCount = fFont.countText(text, byteLength);
- fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType,
- fTotalGlyphCount));
-
- const char* stop = text + byteLength;
-
- // Measure first if needed.
- if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
- SkFixed stopX = 0;
- SkFixed stopY = 0;
-
- const char* textPtr = text;
- while (textPtr < stop) {
- // We don't need x, y here, since all subpixel variants will have the
- // same advance.
- const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr, 0, 0);
-
- stopX += glyph.fAdvanceX;
- stopY += glyph.fAdvanceY;
- }
- SkASSERT(textPtr == stop);
-
- SkScalar alignX = SkFixedToScalar(stopX) * fTextRatio;
- SkScalar alignY = SkFixedToScalar(stopY) * fTextRatio;
-
- if (fFont.getTextAlign() == SkPaint::kCenter_Align) {
- alignX = SkScalarHalf(alignX);
- alignY = SkScalarHalf(alignY);
- }
-
- x -= alignX;
- y -= alignY;
- }
-
- SkAutoKern autokern;
-
- SkFixed fixedSizeRatio = SkScalarToFixed(fTextRatio);
-
- SkFixed fx = SkScalarToFixed(x);
- SkFixed fy = SkScalarToFixed(y);
- FallbackBlobBuilder fallback;
- while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
- fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
- if (glyph.fWidth) {
- this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)),
- &fallback);
- }
-
- fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
- fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
- }
-
- fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount));
-}
-
-void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength,
- const SkScalar pos[], int scalarsPerPosition,
- const SkPoint& offset) {
- SkASSERT(byteLength == 0 || text != nullptr);
- SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
-
- SkGlyphCache* glyphCache = this->getGlyphCache();
- SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
-
- fTotalGlyphCount = fFont.countText(text, byteLength);
- fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType,
- fTotalGlyphCount));
-
- const char* stop = text + byteLength;
-
- SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
- SkTextAlignProc alignProc(fFont.getTextAlign());
- FallbackBlobBuilder fallback;
- while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
- if (glyph.fWidth) {
- SkPoint tmsLoc;
- tmsProc(pos, &tmsLoc);
- SkPoint loc;
- alignProc(tmsLoc, glyph, &loc);
-
- this->appendGlyph(glyph, loc, &fallback);
- }
- pos += scalarsPerPosition;
- }
-
- fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount));
-}
-
-GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx) const {
- GrPathRange* glyphs = static_cast<GrPathRange*>(
- ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKey));
- if (nullptr == glyphs) {
- if (fUsingRawGlyphPaths) {
- glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(), nullptr, fStroke);
- } else {
- SkGlyphCache* cache = this->getGlyphCache();
- glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerContext()->getTypeface(),
- &cache->getDescriptor(),
- fStroke);
- }
- ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyphs);
- }
- return glyphs;
-}
-
-inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph,
- const SkPoint& pos,
- FallbackBlobBuilder* fallback) {
- // Stick the glyphs we can't draw into the fallback text blob.
- if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
- if (!fallback->isInitialized()) {
- fallback->init(fFont, fTextRatio);
- }
- fallback->appendGlyph(glyph.getGlyphID(), pos);
- } else {
- fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(),
- fTextInverseRatio * pos.y());
- }
-}
-
-void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
- GrDrawContext* dc,
- GrPipelineBuilder* pipelineBuilder,
- GrColor color,
- const SkMatrix& viewMatrix,
- SkScalar x, SkScalar y,
- const SkIRect& clipBounds,
- GrTextContext* fallbackTextContext,
- const SkPaint& originalSkPaint) const {
- SkASSERT(fInstanceData);
- SkASSERT(dc->accessRenderTarget()->isStencilBufferMultisampled() || !fFont.isAntiAlias());
-
- if (fInstanceData->count()) {
- pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias());
-
- GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
- kZero_StencilOp,
- kKeep_StencilOp,
- kNotEqual_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
- *pipelineBuilder->stencil() = kStencilPass;
-
- SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx));
- if (fLastDrawnGlyphsID != glyphs->getUniqueID()) {
- // Either this is the first draw or the glyphs object was purged since last draw.
- glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count());
- fLastDrawnGlyphsID = glyphs->getUniqueID();
- }
-
- // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy
- // the entire dst. Realistically this is a moot point, because any context that supports
- // NV_path_rendering will also support NV_blend_equation_advanced.
- // For clipping we'll just skip any optimizations based on the bounds. This does, however,
- // hurt batching.
- SkRect bounds = SkRect::MakeIWH(pipelineBuilder->getRenderTarget()->width(),
- pipelineBuilder->getRenderTarget()->height());
-
- SkAutoTUnref<GrDrawPathBatchBase> batch(
- GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRatio * x,
- fTextInverseRatio * y, color,
- GrPathRendering::kWinding_FillType, glyphs, fInstanceData,
- bounds));
-
- dc->drawPathBatch(*pipelineBuilder, batch);
- }
-
- if (fFallbackTextBlob) {
- SkPaint fallbackSkPaint(originalSkPaint);
- fStroke.applyToPaint(&fallbackSkPaint);
- if (!fStroke.isFillStyle()) {
- fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
- }
-
- fallbackTextContext->drawTextBlob(dc, pipelineBuilder->clip(), fallbackSkPaint, viewMatrix,
- fFallbackTextBlob, x, y, nullptr, clipBounds);
- }
-}
-
-SkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const {
- if (!fDetachedGlyphCache) {
- fDetachedGlyphCache = fFont.detachCache(nullptr, nullptr, true /*ignoreGamma*/);
- }
- return fDetachedGlyphCache;
-}
-
-
-void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const {
- if (fDetachedGlyphCache) {
- SkGlyphCache::AttachCache(fDetachedGlyphCache);
- fDetachedGlyphCache = nullptr;
- }
-}
-
-size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const {
- size_t size = sizeof(TextRun) + fGlyphPathsKey.size();
- // The instance data always reserves enough space for every glyph.
- size += (fTotalGlyphCount + fFallbackGlyphCount) * (sizeof(uint16_t) + 2 * sizeof(float));
- if (fInstanceData) {
- size += sizeof(InstanceData);
- }
- if (fFallbackTextBlob) {
- size += sizeof(SkTextBlob);
- }
- return size;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font,
- SkScalar textRatio) {
- SkASSERT(!this->isInitialized());
- fBuilder.reset(new SkTextBlobBuilder);
- fFont = font;
- fFont.setTextAlign(SkPaint::kLeft_Align); // The glyph positions will already account for align.
- fFont.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color glyphs
- // show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved.
- fFont.setSubpixelText(false);
- fFont.setTextSize(fFont.getTextSize() * textRatio);
- fBuffIdx = 0;
-}
-
-void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t glyphId,
- const SkPoint& pos) {
- SkASSERT(this->isInitialized());
- if (fBuffIdx >= kWriteBufferSize) {
- this->flush();
- }
- fGlyphIds[fBuffIdx] = glyphId;
- fPositions[fBuffIdx] = pos;
- fBuffIdx++;
- fCount++;
-}
-
-void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() {
- SkASSERT(this->isInitialized());
- SkASSERT(fBuffIdx <= kWriteBufferSize);
- if (!fBuffIdx) {
- return;
- }
- // This will automatically merge with previous runs since we use the same font.
- const SkTextBlobBuilder::RunBuffer& buff = fBuilder->allocRunPos(fFont, fBuffIdx);
- memcpy(buff.glyphs, fGlyphIds, fBuffIdx * sizeof(uint16_t));
- memcpy(buff.pos, fPositions[0].asScalars(), fBuffIdx * 2 * sizeof(SkScalar));
- fBuffIdx = 0;
-}
-
-const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeeded(int *count) {
- *count = fCount;
- if (fCount) {
- this->flush();
- return fBuilder->build();
- }
- return nullptr;
-}
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | src/gpu/GrTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698