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

Unified Diff: src/gpu/GrStencilAndCoverTextContext.cpp

Issue 400713003: Add a GrPathRange class (Closed) Base URL: https://skia.googlesource.com/skia.git@clupload-ispath
Patch Set: Fix more windows trivial warningswq Created 6 years, 5 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
Index: src/gpu/GrStencilAndCoverTextContext.cpp
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 637c85a997d8942da5c725777b8bef544fcf0227..65c26423d1391edd69193620234af1e344e5303f 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -7,11 +7,9 @@
#include "GrStencilAndCoverTextContext.h"
#include "GrDrawTarget.h"
-#include "GrFontScaler.h"
#include "GrGpu.h"
#include "GrPath.h"
-#include "GrTextStrike.h"
-#include "GrTextStrike_impl.h"
+#include "GrPathRange.h"
#include "SkAutoKern.h"
#include "SkDraw.h"
#include "SkDrawProcs.h"
@@ -20,12 +18,95 @@
#include "SkPath.h"
#include "SkTextMapStateProc.h"
-static const int kMaxReservedGlyphs = 64;
+class GrStencilAndCoverTextContext::GlyphPathRange : public GrCacheable {
+ static const int kMaxGlyphCount = 1 << 16; // Glyph IDs are uint16_t's
+ static const int kGlyphGroupSize = 16; // Glyphs get tracked in groups of 16
+
+public:
+ static GlyphPathRange* Create(GrContext* context,
+ SkGlyphCache* cache,
+ const SkStrokeRec& stroke) {
+ static const GrCacheID::Domain gGlyphPathRangeDomain = GrCacheID::GenerateDomain();
+
+ GrCacheID::Key key;
+ key.fData32[0] = cache->getDescriptor().getChecksum();
+ key.fData32[1] = cache->getScalerContext()->getTypeface()->uniqueID();
+ key.fData64[1] = GrPath::ComputeStrokeKey(stroke);
+
+ GrResourceKey resourceKey(GrCacheID(gGlyphPathRangeDomain, key),
+ GrPathRange::resourceType(), 0);
+ SkAutoTUnref<GlyphPathRange> glyphs(
+ static_cast<GlyphPathRange*>(context->findAndRefCachedResource(resourceKey)));
+
+ if (NULL == glyphs ||
+ !glyphs->fDesc->equals(cache->getDescriptor() /*checksum collision*/)) {
+ glyphs.reset(SkNEW_ARGS(GlyphPathRange, (context, cache->getDescriptor(), stroke)));
+ context->addResourceToCache(resourceKey, glyphs);
+ }
+
+ return glyphs.detach();
+ }
+
+ const GrPathRange* pathRange() const { return fPathRange.get(); }
+
+ void preloadGlyph(uint16_t glyphID, SkGlyphCache* cache) {
+ const uint16_t groupIndex = glyphID / kGlyphGroupSize;
+ const uint16_t groupByte = groupIndex >> 3;
+ const uint8_t groupBit = 1 << (groupIndex & 7);
+
+ const bool hasGlyph = 0 != (fLoadedGlyphs[groupByte] & groupBit);
+ if (hasGlyph) {
+ return;
+ }
+
+ // We track which glyphs are loaded in groups of kGlyphGroupSize. To
+ // mark a glyph loaded we need to load the entire group.
+ const uint16_t groupFirstID = groupIndex * kGlyphGroupSize;
+ const uint16_t groupLastID = groupFirstID + kGlyphGroupSize - 1;
+ SkPath skPath;
+ for (int id = groupFirstID; id <= groupLastID; ++id) {
+ const SkGlyph& skGlyph = cache->getGlyphIDMetrics(id);
+ if (const SkPath* skPath = cache->findPath(skGlyph)) {
+ fPathRange->initAt(id, *skPath);
+ } // GrGpu::drawPaths will silently ignore undefined paths.
+ }
+
+ fLoadedGlyphs[groupByte] |= groupBit;
+ this->didChangeGpuMemorySize();
+ }
+
+ // GrCacheable overrides
+ virtual size_t gpuMemorySize() const SK_OVERRIDE { return fPathRange->gpuMemorySize(); }
+ virtual bool isValidOnGpu() const SK_OVERRIDE { return fPathRange->isValidOnGpu(); }
+
+private:
+ GlyphPathRange(GrContext* context, const SkDescriptor& desc, const SkStrokeRec& stroke)
+ : fDesc(desc.copy())
+ // We reserve a range of kMaxGlyphCount paths because of fallbacks fonts. We
+ // can't know exactly how many glyphs we might need without preloading every
+ // fallback, which we don't want to do at this point.
+ , fPathRange(context->getGpu()->createPathRange(kMaxGlyphCount, stroke)) {
+ memset(fLoadedGlyphs, 0, sizeof(fLoadedGlyphs));
+ }
+
+ ~GlyphPathRange() {
+ SkDescriptor::Free(fDesc);
+ }
+
+ static const int kMaxGroupCount = (kMaxGlyphCount + (kGlyphGroupSize - 1)) / kGlyphGroupSize;
+ SkDescriptor* const fDesc;
+ uint8_t fLoadedGlyphs[(kMaxGroupCount + 7) >> 3]; // One bit per glyph group
+ SkAutoTUnref<GrPathRange> fPathRange;
+
+ typedef GrCacheable INHERITED;
+};
+
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(
GrContext* context, const SkDeviceProperties& properties)
: GrTextContext(context, properties)
- , fStroke(SkStrokeRec::kFill_InitStyle) {
+ , fStroke(SkStrokeRec::kFill_InitStyle)
+ , fPendingGlyphCount(0) {
}
GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
@@ -73,10 +154,8 @@ void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, glyphCacheTransform);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* scaler = GetGrFontScaler(cache);
- GrTextStrike* strike =
- fContext->getFontCache()->getStrike(scaler, true);
+ fGlyphCache = autoCache.getCache();
+ fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
const char* stop = text + byteLength;
@@ -89,7 +168,7 @@ void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
while (textPtr < stop) {
// We don't need x, y here, since all subpixel variants will have the
// same advance.
- const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &textPtr, 0, 0);
stopX += glyph.fAdvanceX;
stopY += glyph.fAdvanceY;
@@ -115,17 +194,10 @@ void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
SkFixed fx = SkScalarToFixed(x);
SkFixed fy = SkScalarToFixed(y);
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
fx += SkFixedMul_portable(autokern.adjust(glyph), fixedSizeRatio);
if (glyph.fWidth) {
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed()),
- SkPoint::Make(
- SkFixedToScalar(fx),
- SkFixedToScalar(fy)),
- strike,
- scaler);
+ this->appendGlyph(glyph.getGlyphID(), SkFixedToScalar(fx), SkFixedToScalar(fy));
}
fx += SkFixedMul_portable(glyph.fAdvanceX, fixedSizeRatio);
@@ -164,10 +236,8 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint,
SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
- SkGlyphCache* cache = autoCache.getCache();
- GrFontScaler* scaler = GetGrFontScaler(cache);
- GrTextStrike* strike =
- fContext->getFontCache()->getStrike(scaler, true);
+ fGlyphCache = autoCache.getCache();
+ fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
const char* stop = text + byteLength;
SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign());
@@ -177,33 +247,22 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint,
while (text < stop) {
SkPoint loc;
tmsProc(pos, &loc);
- const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
if (glyph.fWidth) {
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed()),
- loc,
- strike,
- scaler);
+ this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y());
}
pos += scalarsPerPosition;
}
} else {
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
if (glyph.fWidth) {
SkPoint tmsLoc;
tmsProc(pos, &tmsLoc);
SkPoint loc;
alignProc(tmsLoc, glyph, &loc);
- this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed()),
- loc,
- strike,
- scaler);
-
+ this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y());
}
pos += scalarsPerPosition;
}
@@ -305,62 +364,45 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
*fDrawTarget->drawState()->stencil() = kStencilPass;
- size_t reserveAmount;
- switch (skPaint.getTextEncoding()) {
- default:
- SkASSERT(false);
- case SkPaint::kUTF8_TextEncoding:
- reserveAmount = textByteLength;
- break;
- case SkPaint::kUTF16_TextEncoding:
- reserveAmount = textByteLength / 2;
- break;
- case SkPaint::kUTF32_TextEncoding:
- case SkPaint::kGlyphID_TextEncoding:
- reserveAmount = textByteLength / 4;
- break;
+ SkASSERT(0 == fPendingGlyphCount);
+}
+
+inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) {
+ if (fPendingGlyphCount >= kGlyphBufferSize) {
+ this->flush();
}
- fPaths.setReserve(reserveAmount);
- fTransforms.setReserve(reserveAmount);
+
+ fGlyphs->preloadGlyph(glyphID, fGlyphCache);
+
+ fIndexBuffer[fPendingGlyphCount] = glyphID;
+ fTransformBuffer[6 * fPendingGlyphCount + 0] = fTextRatio;
+ fTransformBuffer[6 * fPendingGlyphCount + 1] = 0;
+ fTransformBuffer[6 * fPendingGlyphCount + 2] = x;
+ fTransformBuffer[6 * fPendingGlyphCount + 3] = 0;
+ fTransformBuffer[6 * fPendingGlyphCount + 4] = fTextRatio;
+ fTransformBuffer[6 * fPendingGlyphCount + 5] = y;
+
+ ++fPendingGlyphCount;
}
-inline void GrStencilAndCoverTextContext::appendGlyph(GrGlyph::PackedID glyphID,
- const SkPoint& pos,
- GrTextStrike* strike,
- GrFontScaler* scaler) {
- GrGlyph* glyph = strike->getGlyph(glyphID, scaler);
- if (NULL == glyph || glyph->fBounds.isEmpty()) {
+void GrStencilAndCoverTextContext::flush() {
+ if (0 == fPendingGlyphCount) {
return;
}
- if (scaler->getGlyphPath(glyph->glyphID(), &fTmpPath)) {
- if (!fTmpPath.isEmpty()) {
- *fPaths.append() = fContext->createPath(fTmpPath, fStroke);
- SkMatrix* t = fTransforms.append();
- t->setTranslate(pos.fX, pos.fY);
- t->preScale(fTextRatio, fTextRatio);
- }
- }
+ fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCount,
+ fTransformBuffer, GrDrawTarget::kAffine_PathTransformType,
+ SkPath::kWinding_FillType);
+
+ fPendingGlyphCount = 0;
}
void GrStencilAndCoverTextContext::finish() {
- if (fPaths.count() > 0) {
- fDrawTarget->drawPaths(static_cast<size_t>(fPaths.count()),
- fPaths.begin(), fTransforms.begin(),
- SkPath::kWinding_FillType, fStroke.getStyle());
+ this->flush();
- for (int i = 0; i < fPaths.count(); ++i) {
- fPaths[i]->unref();
- }
- if (fPaths.count() > kMaxReservedGlyphs) {
- fPaths.reset();
- fTransforms.reset();
- } else {
- fPaths.rewind();
- fTransforms.rewind();
- }
- }
- fTmpPath.reset();
+ SkSafeUnref(fGlyphs);
+ fGlyphs = NULL;
+ fGlyphCache = NULL;
fDrawTarget->drawState()->stencil()->setDisabled();
fStateRestore.set(NULL);

Powered by Google App Engine
This is Rietveld 408576698