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

Unified Diff: src/gpu/GrBitmapTextContext.cpp

Issue 1045723010: move Atlas Text Context to its own file (Closed) Base URL: https://skia.googlesource.com/skia.git@bmptext3
Patch Set: rebase Created 5 years, 9 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/GrBitmapTextContext.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrBitmapTextContext.cpp
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 605703d1c62906ff579c84a4e923d972e92003a3..efce516b79789f245e548822c9440da1413e8894 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -48,507 +48,6 @@ static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof
static const int kVerticesPerGlyph = 4;
static const int kIndicesPerGlyph = 6;
-};
-
-// TODO
-// More tests
-// move to SkCache
-// handle textblobs where the whole run is larger than the cache size
-// TODO implement micro speedy hash map for fast refing of glyphs
-
-GrBitmapTextContextB::GrBitmapTextContextB(GrContext* context,
- SkGpuDevice* gpuDevice,
- const SkDeviceProperties& properties)
- : INHERITED(context, gpuDevice, properties) {
- fCurrStrike = NULL;
-}
-
-void GrBitmapTextContextB::ClearCacheEntry(uint32_t key, BitmapTextBlob** blob) {
- (*blob)->unref();
-}
-
-GrBitmapTextContextB::~GrBitmapTextContextB() {
- fCache.foreach(&GrBitmapTextContextB::ClearCacheEntry);
-}
-
-GrBitmapTextContextB* GrBitmapTextContextB::Create(GrContext* context,
- SkGpuDevice* gpuDevice,
- const SkDeviceProperties& props) {
- return SkNEW_ARGS(GrBitmapTextContextB, (context, gpuDevice, props));
-}
-
-bool GrBitmapTextContextB::canDraw(const GrRenderTarget*,
- const GrClip&,
- const GrPaint&,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix) {
- return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
-}
-
-inline void GrBitmapTextContextB::init(GrRenderTarget* rt, const GrClip& clip,
- const GrPaint& paint, const SkPaint& skPaint,
- const SkIRect& regionClipBounds) {
- INHERITED::init(rt, clip, paint, skPaint, regionClipBounds);
-
- fCurrStrike = NULL;
-}
-
-bool GrBitmapTextContextB::MustRegenerateBlob(const BitmapTextBlob& blob, const SkPaint& paint,
- const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
- // We always regenerate blobs with patheffects or mask filters we could cache these
- // TODO find some way to cache the maskfilter / patheffects on the textblob
- return !blob.fViewMatrix.cheapEqualTo(viewMatrix) || blob.fX != x || blob.fY != y ||
- paint.getMaskFilter() || paint.getPathEffect() || paint.getStyle() != blob.fStyle;
-}
-
-
-inline SkGlyphCache* GrBitmapTextContextB::setupCache(BitmapTextBlob::Run* run,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix) {
- skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &viewMatrix, false);
- run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
- return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc());
-}
-
-inline void GrBitmapTextContextB::BlobGlyphCount(int* glyphCount, int* runCount,
- const SkTextBlob* blob) {
- SkTextBlob::RunIterator itCounter(blob);
- for (; !itCounter.done(); itCounter.next(), (*runCount)++) {
- *glyphCount += itCounter.glyphCount();
- }
-}
-
-GrBitmapTextContextB::BitmapTextBlob* GrBitmapTextContextB::CreateBlob(int glyphCount,
- int runCount) {
- // We allocate size for the BitmapTextBlob itself, plus size for the vertices array,
- // and size for the glyphIds array.
- SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCDTextVASize,
- vertex_attribute_changed);
- size_t verticesCount = glyphCount * kVerticesPerGlyph * kGrayTextVASize;
- size_t length = sizeof(BitmapTextBlob) +
- verticesCount +
- glyphCount * sizeof(GrGlyph::PackedID) +
- sizeof(BitmapTextBlob::Run) * runCount;
-
- BitmapTextBlob* cacheBlob = SkNEW_PLACEMENT(sk_malloc_throw(length), BitmapTextBlob);
-
- // setup offsets for vertices / glyphs
- cacheBlob->fVertices = sizeof(BitmapTextBlob) + reinterpret_cast<unsigned char*>(cacheBlob);
- cacheBlob->fGlyphIDs =
- reinterpret_cast<GrGlyph::PackedID*>(cacheBlob->fVertices + verticesCount);
- cacheBlob->fRuns = reinterpret_cast<BitmapTextBlob::Run*>(cacheBlob->fGlyphIDs + glyphCount);
-
- // Initialize runs
- for (int i = 0; i < runCount; i++) {
- SkNEW_PLACEMENT(&cacheBlob->fRuns[i], BitmapTextBlob::Run);
- }
- cacheBlob->fRunCount = runCount;
- return cacheBlob;
-}
-
-void GrBitmapTextContextB::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
- const SkPaint& skPaint, const SkMatrix& viewMatrix,
- const SkTextBlob* blob, SkScalar x, SkScalar y,
- SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
- BitmapTextBlob* cacheBlob;
- BitmapTextBlob** foundBlob = fCache.find(blob->uniqueID());
- SkIRect clipRect;
- clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
-
- if (foundBlob) {
- cacheBlob = *foundBlob;
- if (MustRegenerateBlob(*cacheBlob, skPaint, viewMatrix, x, y)) {
- // We have to remake the blob because changes may invalidate our masks.
- // TODO we could probably get away reuse most of the time if the pointer is unique,
- // but we'd have to clear the subrun information
- cacheBlob->unref();
- int glyphCount = 0;
- int runCount = 0;
- BlobGlyphCount(&glyphCount, &runCount, blob);
- cacheBlob = CreateBlob(glyphCount, runCount);
- fCache.set(blob->uniqueID(), cacheBlob);
- this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter,
- clipRect);
- }
- } else {
- int glyphCount = 0;
- int runCount = 0;
- BlobGlyphCount(&glyphCount, &runCount, blob);
- cacheBlob = CreateBlob(glyphCount, runCount);
- fCache.set(blob->uniqueID(), cacheBlob);
- this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, clipRect);
- }
-
- // Though for the time being runs in the textblob can override the paint, they only touch font
- // info.
- GrPaint grPaint;
- SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
-
- this->flush(fContext->getTextTarget(), cacheBlob, rt, grPaint, clip, viewMatrix,
- fSkPaint.getAlpha());
-}
-
-void GrBitmapTextContextB::regenerateTextBlob(BitmapTextBlob* cacheBlob,
- const SkPaint& skPaint, const SkMatrix& viewMatrix,
- const SkTextBlob* blob, SkScalar x, SkScalar y,
- SkDrawFilter* drawFilter, const SkIRect& clipRect) {
- cacheBlob->fViewMatrix = viewMatrix;
- cacheBlob->fX = x;
- cacheBlob->fY = y;
- cacheBlob->fStyle = skPaint.getStyle();
-
- // Regenerate textblob
- SkPaint runPaint = skPaint;
- SkTextBlob::RunIterator it(blob);
- for (int run = 0; !it.done(); it.next(), run++) {
- int glyphCount = it.glyphCount();
- size_t textLen = glyphCount * sizeof(uint16_t);
- const SkPoint& offset = it.offset();
- // applyFontToPaint() always overwrites the exact same attributes,
- // so it is safe to not re-seed the paint for this reason.
- it.applyFontToPaint(&runPaint);
-
- if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
- // A false return from filter() means we should abort the current draw.
- runPaint = skPaint;
- continue;
- }
-
- runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
-
- SkGlyphCache* cache = this->setupCache(&cacheBlob->fRuns[run], runPaint, viewMatrix);
-
- // setup vertex / glyphIndex for the new run
- if (run > 0) {
- PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back();
- PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back();
-
- newRun.fVertexStartIndex = lastRun.fVertexEndIndex;
- newRun.fVertexEndIndex = lastRun.fVertexEndIndex;
-
- newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex;
- newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex;
- }
-
- switch (it.positioning()) {
- case SkTextBlob::kDefault_Positioning:
- this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatrix,
- (const char *)it.glyphs(), textLen,
- x + offset.x(), y + offset.y(), clipRect);
- break;
- case SkTextBlob::kHorizontal_Positioning:
- this->internalDrawPosText(cacheBlob, run, cache, runPaint, viewMatrix,
- (const char*)it.glyphs(), textLen, it.pos(), 1,
- SkPoint::Make(x, y + offset.y()), clipRect);
- break;
- case SkTextBlob::kFull_Positioning:
- this->internalDrawPosText(cacheBlob, run, cache, runPaint, viewMatrix,
- (const char*)it.glyphs(), textLen, it.pos(), 2,
- SkPoint::Make(x, y), clipRect);
- break;
- }
-
- if (drawFilter) {
- // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
- runPaint = skPaint;
- }
-
- SkGlyphCache::AttachCache(cache);
- }
-}
-
-void GrBitmapTextContextB::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) {
- int glyphCount = skPaint.countText(text, byteLength);
- SkAutoTUnref<BitmapTextBlob> blob(CreateBlob(glyphCount, 1));
- blob->fViewMatrix = viewMatrix;
- blob->fX = x;
- blob->fY = y;
- blob->fStyle = skPaint.getStyle();
-
- SkIRect clipRect;
- clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
-
- // setup cache
- SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix);
- this->internalDrawText(blob, 0, cache, skPaint, viewMatrix, text, byteLength, x, y, clipRect);
- SkGlyphCache::AttachCache(cache);
-
- this->flush(fContext->getTextTarget(), blob, rt, paint, clip, viewMatrix, skPaint.getAlpha());
-}
-
-void GrBitmapTextContextB::internalDrawText(BitmapTextBlob* blob, int runIndex,
- SkGlyphCache* cache, const SkPaint& skPaint,
- const SkMatrix& viewMatrix,
- const char text[], size_t byteLength,
- SkScalar x, SkScalar y, const SkIRect& clipRect) {
- SkASSERT(byteLength == 0 || text != NULL);
-
- // nothing to draw
- if (text == NULL || byteLength == 0) {
- return;
- }
-
- fCurrStrike = NULL;
- SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc();
-
- // Get GrFontScaler from cache
- 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
- if (skPaint.getTextAlign() != SkPaint::kLeft_Align) {
- SkVector stopVector;
- MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector);
-
- SkScalar stopX = stopVector.fX;
- SkScalar stopY = stopVector.fY;
-
- if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
- stopX = SkScalarHalf(stopX);
- stopY = SkScalarHalf(stopY);
- }
- x -= stopX;
- y -= stopY;
- }
-
- 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);
-
- while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
-
- fx += autokern.adjust(glyph);
-
- if (glyph.fWidth) {
- this->appendGlyph(blob,
- runIndex,
- GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler,
- clipRect);
- }
-
- fx += glyph.fAdvanceX;
- fy += glyph.fAdvanceY;
- }
-}
-
-void GrBitmapTextContextB::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) {
- int glyphCount = skPaint.countText(text, byteLength);
- SkAutoTUnref<BitmapTextBlob> blob(CreateBlob(glyphCount, 1));
- blob->fStyle = skPaint.getStyle();
- blob->fViewMatrix = viewMatrix;
-
- SkIRect clipRect;
- clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
-
- // setup cache
- SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix);
- this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLength, pos,
- scalarsPerPosition, offset, clipRect);
- SkGlyphCache::AttachCache(cache);
-
- this->flush(fContext->getTextTarget(), blob, rt, paint, clip, viewMatrix, fSkPaint.getAlpha());
-}
-
-void GrBitmapTextContextB::internalDrawPosText(BitmapTextBlob* blob, int runIndex,
- SkGlyphCache* cache, const SkPaint& skPaint,
- const SkMatrix& viewMatrix,
- const char text[], size_t byteLength,
- const SkScalar pos[], int scalarsPerPosition,
- const SkPoint& offset, const SkIRect& clipRect) {
- SkASSERT(byteLength == 0 || text != NULL);
- SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
-
- // nothing to draw
- if (text == NULL || byteLength == 0) {
- return;
- }
-
- fCurrStrike = NULL;
- SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc();
-
- // Get GrFontScaler from cache
- GrFontScaler* fontScaler = GetGrFontScaler(cache);
-
- const char* stop = text + byteLength;
- SkTextAlignProc alignProc(skPaint.getTextAlign());
- SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition);
- SkScalar halfSampleX = 0, halfSampleY = 0;
-
- if (cache->isSubpixel()) {
- // maybe we should skip the rounding if linearText is set
- SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
-
- SkFixed fxMask = ~0;
- SkFixed fyMask = ~0;
- if (kX_SkAxisAlignment == baseline) {
- fyMask = 0;
- halfSampleY = SK_ScalarHalf;
- } else if (kY_SkAxisAlignment == baseline) {
- fxMask = 0;
- halfSampleX = SK_ScalarHalf;
- }
-
- if (SkPaint::kLeft_Align == skPaint.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(blob,
- runIndex,
- GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler,
- clipRect);
- }
- 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, &currentText,
- 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(blob,
- runIndex,
- GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler,
- clipRect);
- }
- pos += scalarsPerPosition;
- }
- }
- } else { // not subpixel
-
- if (SkPaint::kLeft_Align == skPaint.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); //halfSampleX;
- Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf); //halfSampleY;
- this->appendGlyph(blob,
- runIndex,
- GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler,
- clipRect);
- }
- 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); //halfSampleX;
- Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf); //halfSampleY;
- this->appendGlyph(blob,
- runIndex,
- GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed(),
- GrGlyph::kCoverage_MaskStyle),
- Sk48Dot16FloorToInt(fx),
- Sk48Dot16FloorToInt(fy),
- fontScaler,
- clipRect);
- }
- pos += scalarsPerPosition;
- }
- }
- }
-}
static size_t get_vertex_stride(GrMaskFormat maskFormat) {
switch (maskFormat) {
@@ -561,501 +60,8 @@ static size_t get_vertex_stride(GrMaskFormat maskFormat) {
}
}
-void GrBitmapTextContextB::appendGlyph(BitmapTextBlob* blob, int runIndex, GrGlyph::PackedID packed,
- int vx, int vy, GrFontScaler* scaler,
- const SkIRect& clipRect) {
- if (NULL == fCurrStrike) {
- fCurrStrike = fContext->getBatchFontCache()->getStrike(scaler);
- }
-
- GrGlyph* glyph = fCurrStrike->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 (clipRect.quickReject(x, y, x + width, y + height)) {
- return;
- }
-
- // If the glyph is too large we fall back to paths
- if (fCurrStrike->glyphTooLargeForAtlas(glyph)) {
- if (NULL == glyph->fPath) {
- SkPath* path = SkNEW(SkPath);
- if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
- // flag the glyph as being dead?
- SkDELETE(path);
- return;
- }
- glyph->fPath = path;
- }
- SkASSERT(glyph->fPath);
- blob->fBigGlyphs.push_back(BitmapTextBlob::BigGlyph(*glyph->fPath, vx, vy));
- return;
- }
-
- Run& run = blob->fRuns[runIndex];
-
- GrMaskFormat format = glyph->fMaskFormat;
-
- PerSubRunInfo* subRun = &run.fSubRunInfo.back();
- if (run.fInitialized && subRun->fMaskFormat != format) {
- PerSubRunInfo* newSubRun = &run.fSubRunInfo.push_back();
- newSubRun->fGlyphStartIndex = subRun->fGlyphEndIndex;
- newSubRun->fGlyphEndIndex = subRun->fGlyphEndIndex;
-
- newSubRun->fVertexStartIndex = subRun->fVertexEndIndex;
- newSubRun->fVertexEndIndex = subRun->fVertexEndIndex;
-
- subRun = newSubRun;
- }
-
- run.fInitialized = true;
- subRun->fMaskFormat = format;
- blob->fGlyphIDs[subRun->fGlyphEndIndex] = packed;
-
- size_t vertexStride = get_vertex_stride(format);
-
- SkRect r;
- r.fLeft = SkIntToScalar(x);
- r.fTop = SkIntToScalar(y);
- r.fRight = r.fLeft + SkIntToScalar(width);
- r.fBottom = r.fTop + SkIntToScalar(height);
-
- run.fVertexBounds.joinNonEmptyArg(r);
- GrColor color = fPaint.getColor();
- run.fColor = color;
-
- intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVertexEndIndex);
-
- // V0
- SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fLeft, r.fTop);
- if (kA8_GrMaskFormat == format) {
- SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *colorPtr = color;
- }
- vertex += vertexStride;
-
- // V1
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fLeft, r.fBottom);
- if (kA8_GrMaskFormat == format) {
- SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *colorPtr = color;
- }
- vertex += vertexStride;
-
- // V2
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fRight, r.fBottom);
- if (kA8_GrMaskFormat == format) {
- SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *colorPtr = color;
- }
- vertex += vertexStride;
-
- // V3
- position = reinterpret_cast<SkPoint*>(vertex);
- position->set(r.fRight, r.fTop);
- if (kA8_GrMaskFormat == format) {
- SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
- *colorPtr = color;
- }
-
- subRun->fGlyphEndIndex++;
- subRun->fVertexEndIndex += vertexStride * kVerticesPerGlyph;
-}
-
-class BitmapTextBatch : public GrBatch {
-public:
- typedef GrBitmapTextContextB::BitmapTextBlob Blob;
- typedef Blob::Run Run;
- typedef Run::SubRunInfo TextInfo;
- struct Geometry {
- Geometry() {}
- Geometry(const Geometry& geometry)
- : fBlob(SkRef(geometry.fBlob.get()))
- , fRun(geometry.fRun)
- , fSubRun(geometry.fSubRun)
- , fColor(geometry.fColor) {}
- SkAutoTUnref<Blob> fBlob;
- int fRun;
- int fSubRun;
- GrColor fColor;
- };
-
- static GrBatch* Create(const Geometry& geometry, GrColor color, GrMaskFormat maskFormat,
- int glyphCount, GrBatchFontCache* fontCache) {
- return SkNEW_ARGS(BitmapTextBatch, (geometry, color, maskFormat, glyphCount, fontCache));
- }
-
- const char* name() const override { return "BitmapTextBatch"; }
-
- void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
- if (kARGB_GrMaskFormat == fMaskFormat) {
- out->setUnknownFourComponents();
- } else {
- out->setKnownFourComponents(fBatch.fColor);
- }
- }
-
- void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
- if (kARGB_GrMaskFormat != fMaskFormat) {
- if (GrPixelConfigIsAlphaOnly(fPixelConfig)) {
- out->setUnknownSingleComponent();
- } else if (GrPixelConfigIsOpaque(fPixelConfig)) {
- out->setUnknownOpaqueFourComponents();
- out->setUsingLCDCoverage();
- } else {
- out->setUnknownFourComponents();
- out->setUsingLCDCoverage();
- }
- } else {
- out->setKnownSingleComponent(0xff);
- }
- }
-
- void initBatchTracker(const GrPipelineInfo& init) override {
- // Handle any color overrides
- if (init.fColorIgnored) {
- fBatch.fColor = GrColor_ILLEGAL;
- } else if (GrColor_ILLEGAL != init.fOverrideColor) {
- fBatch.fColor = init.fOverrideColor;
- }
-
- // setup batch properties
- fBatch.fColorIgnored = init.fColorIgnored;
- fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
- fBatch.fCoverageIgnored = init.fCoverageIgnored;
- }
-
- void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
- // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
- // TODO actually only invert if we don't have RGBA
- SkMatrix localMatrix;
- if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
- SkDebugf("Cannot invert viewmatrix\n");
- return;
- }
-
- GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
- // This will be ignored in the non A8 case
- bool opaqueVertexColors = GrColorIsOpaque(this->color());
- SkAutoTUnref<const GrGeometryProcessor> gp(
- GrBitmapTextGeoProc::Create(this->color(),
- fFontCache->getTexture(fMaskFormat),
- params,
- fMaskFormat,
- opaqueVertexColors,
- localMatrix));
-
- size_t vertexStride = gp->getVertexStride();
- SkASSERT(vertexStride == get_vertex_stride(fMaskFormat));
-
- this->initDraw(batchTarget, gp, pipeline);
-
- int glyphCount = this->numGlyphs();
- int instanceCount = fGeoData.count();
- const GrVertexBuffer* vertexBuffer;
- int firstVertex;
-
- void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
- glyphCount * kVerticesPerGlyph,
- &vertexBuffer,
- &firstVertex);
- if (!vertices) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
-
- unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices);
-
- // setup drawinfo
- const GrIndexBuffer* quadIndexBuffer = batchTarget->quadIndexBuffer();
- int maxInstancesPerDraw = quadIndexBuffer->maxQuads();
-
- GrDrawTarget::DrawInfo drawInfo;
- drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
- drawInfo.setStartVertex(0);
- drawInfo.setStartIndex(0);
- drawInfo.setVerticesPerInstance(kVerticesPerGlyph);
- drawInfo.setIndicesPerInstance(kIndicesPerGlyph);
- drawInfo.adjustStartVertex(firstVertex);
- drawInfo.setVertexBuffer(vertexBuffer);
- drawInfo.setIndexBuffer(quadIndexBuffer);
-
- int instancesToFlush = 0;
- for (int i = 0; i < instanceCount; i++) {
- Geometry& args = fGeoData[i];
- Blob* blob = args.fBlob;
- Run& run = blob->fRuns[args.fRun];
- TextInfo& info = run.fSubRunInfo[args.fSubRun];
-
- uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat);
- bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlasGen;
- bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColor != args.fColor;
- int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
-
- // We regenerate both texture coords and colors in the blob itself, and update the
- // atlas generation. If we don't end up purging any unused plots, we can avoid
- // regenerating the coords. We could take a finer grained approach to updating texture
- // coords but its not clear if the extra bookkeeping would offset any gains.
- // To avoid looping over the glyphs twice, we do one loop and conditionally update color
- // or coords as needed. One final note, if we have to break a run for an atlas eviction
- // then we can't really trust the atlas has all of the correct data. Atlas evictions
- // should be pretty rare, so we just always regenerate in those cases
- if (regenerateTextureCoords || regenerateColors) {
- // first regenerate texture coordinates / colors if need be
- const SkDescriptor* desc = NULL;
- SkGlyphCache* cache = NULL;
- GrFontScaler* scaler = NULL;
- GrBatchTextStrike* strike = NULL;
- bool brokenRun = false;
- if (regenerateTextureCoords) {
- desc = run.fDescriptor.getDesc();
- cache = SkGlyphCache::DetachCache(run.fTypeface, desc);
- scaler = GrTextContext::GetGrFontScaler(cache);
- strike = fFontCache->getStrike(scaler);
- }
- for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
- GrGlyph::PackedID glyphID = blob->fGlyphIDs[glyphIdx + info.fGlyphStartIndex];
-
- if (regenerateTextureCoords) {
- // Upload the glyph only if needed
- GrGlyph* glyph = strike->getGlyph(glyphID, scaler);
- SkASSERT(glyph);
-
- if (!fFontCache->hasGlyph(glyph) &&
- !strike->addGlyphToAtlas(batchTarget, glyph, scaler)) {
- this->flush(batchTarget, &drawInfo, instancesToFlush,
- maxInstancesPerDraw);
- this->initDraw(batchTarget, gp, pipeline);
- instancesToFlush = 0;
- brokenRun = glyphIdx > 0;
-
- SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(batchTarget, glyph,
- scaler);
- SkASSERT(success);
- }
-
- fFontCache->setGlyphRefToken(glyph, batchTarget->currentToken());
-
- // Texture coords are the last vertex attribute so we get a pointer to the
- // first one and then map with stride in regenerateTextureCoords
- intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
- vertex += info.fVertexStartIndex;
- vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
- vertex += vertexStride - sizeof(SkIPoint16);
-
- this->regenerateTextureCoords(glyph, vertex, vertexStride);
- }
-
- if (regenerateColors) {
- intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
- vertex += info.fVertexStartIndex;
- vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint);
- this->regenerateColors(vertex, vertexStride, args.fColor);
- }
-
- instancesToFlush++;
- }
-
- if (regenerateTextureCoords) {
- SkGlyphCache::AttachCache(cache);
- info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration :
- fFontCache->atlasGeneration(fMaskFormat);
- }
- } else {
- instancesToFlush += glyphCount;
- }
-
- // now copy all vertices
- size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex;
- memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCount);
-
- currVertex += byteCount;
- }
-
- this->flush(batchTarget, &drawInfo, instancesToFlush, maxInstancesPerDraw);
- }
-
- SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
-
-private:
- BitmapTextBatch(const Geometry& geometry, GrColor color, GrMaskFormat maskFormat,
- int glyphCount, GrBatchFontCache* fontCache)
- : fMaskFormat(maskFormat)
- , fPixelConfig(fontCache->getPixelConfig(maskFormat))
- , fFontCache(fontCache) {
- this->initClassID<BitmapTextBatch>();
- fGeoData.push_back(geometry);
- fBatch.fColor = color;
- fBatch.fViewMatrix = geometry.fBlob->fViewMatrix;
- fBatch.fNumGlyphs = glyphCount;
- }
-
- void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexStride) {
- int width = glyph->fBounds.width();
- int height = glyph->fBounds.height();
- int u0 = glyph->fAtlasLocation.fX;
- int v0 = glyph->fAtlasLocation.fY;
- int u1 = u0 + width;
- int v1 = v0 + height;
-
- // we assume texture coords are the last vertex attribute, this is a bit fragile.
- // TODO pass in this offset or something
- SkIPoint16* textureCoords;
- // V0
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
- textureCoords->set(u0, v0);
- vertex += vertexStride;
-
- // V1
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
- textureCoords->set(u0, v1);
- vertex += vertexStride;
-
- // V2
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
- textureCoords->set(u1, v1);
- vertex += vertexStride;
-
- // V3
- textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
- textureCoords->set(u1, v0);
- }
-
- void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) {
- for (int i = 0; i < kVerticesPerGlyph; i++) {
- SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
- *vcolor = color;
- vertex += vertexStride;
- }
- }
-
- void initDraw(GrBatchTarget* batchTarget,
- const GrGeometryProcessor* gp,
- const GrPipeline* pipeline) {
- batchTarget->initDraw(gp, pipeline);
-
- // TODO remove this when batch is everywhere
- GrPipelineInfo init;
- init.fColorIgnored = fBatch.fColorIgnored;
- init.fOverrideColor = GrColor_ILLEGAL;
- init.fCoverageIgnored = fBatch.fCoverageIgnored;
- init.fUsesLocalCoords = this->usesLocalCoords();
- gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
- }
-
- void flush(GrBatchTarget* batchTarget,
- GrDrawTarget::DrawInfo* drawInfo,
- int instanceCount,
- int maxInstancesPerDraw) {
- while (instanceCount) {
- drawInfo->setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
- drawInfo->setVertexCount(drawInfo->instanceCount() * drawInfo->verticesPerInstance());
- drawInfo->setIndexCount(drawInfo->instanceCount() * drawInfo->indicesPerInstance());
-
- batchTarget->draw(*drawInfo);
-
- drawInfo->setStartVertex(drawInfo->startVertex() + drawInfo->vertexCount());
- instanceCount -= drawInfo->instanceCount();
- }
- }
-
- GrColor color() const { return fBatch.fColor; }
- const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
- bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
- int numGlyphs() const { return fBatch.fNumGlyphs; }
-
- bool onCombineIfPossible(GrBatch* t) override {
- BitmapTextBatch* that = t->cast<BitmapTextBatch>();
-
- if (this->fMaskFormat != that->fMaskFormat) {
- return false;
- }
-
- if (this->fMaskFormat != kA8_GrMaskFormat && this->color() != that->color()) {
- return false;
- }
-
- if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
- return false;
- }
-
- fBatch.fNumGlyphs += that->numGlyphs();
- fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
- return true;
- }
-
- struct BatchTracker {
- GrColor fColor;
- SkMatrix fViewMatrix;
- bool fUsesLocalCoords;
- bool fColorIgnored;
- bool fCoverageIgnored;
- int fNumGlyphs;
- };
-
- BatchTracker fBatch;
- SkSTArray<1, Geometry, true> fGeoData;
- GrMaskFormat fMaskFormat;
- GrPixelConfig fPixelConfig;
- GrBatchFontCache* fFontCache;
};
-void GrBitmapTextContextB::flush(GrDrawTarget* target, BitmapTextBlob* blob, GrRenderTarget* rt,
- const GrPaint& paint, const GrClip& clip,
- const SkMatrix& viewMatrix, int paintAlpha) {
- GrPipelineBuilder pipelineBuilder;
- pipelineBuilder.setFromPaint(paint, rt, clip);
-
- GrColor color = paint.getColor();
- for (uint32_t run = 0; run < blob->fRunCount; run++) {
- for (int subRun = 0; subRun < blob->fRuns[run].fSubRunInfo.count(); subRun++) {
- PerSubRunInfo& info = blob->fRuns[run].fSubRunInfo[subRun];
- int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
- if (0 == glyphCount) {
- continue;
- }
-
- GrMaskFormat format = info.fMaskFormat;
- if (kARGB_GrMaskFormat == format) {
- color = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha);
- }
-
- BitmapTextBatch::Geometry geometry;
- geometry.fBlob.reset(SkRef(blob));
- geometry.fRun = run;
- geometry.fSubRun = subRun;
- geometry.fColor = color;
- SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, color, format, glyphCount,
- fContext->getBatchFontCache()));
-
- target->drawBatch(&pipelineBuilder, batch, &blob->fRuns[run].fVertexBounds);
- }
- }
-
- // Now flush big glyphs
- for (int i = 0; i < blob->fBigGlyphs.count(); i++) {
- BitmapTextBlob::BigGlyph& bigGlyph = blob->fBigGlyphs[i];
- SkMatrix translate;
- translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGlyph.fVy));
- SkPath tmpPath(bigGlyph.fPath);
- tmpPath.transform(translate);
- GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
- fContext->drawPath(rt, clip, paint, SkMatrix::I(), tmpPath, strokeInfo);
- }
-}
-
GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
SkGpuDevice* gpuDevice,
const SkDeviceProperties& properties)
« no previous file with comments | « src/gpu/GrBitmapTextContext.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698