diff options
author | 2014-10-16 11:53:30 -0700 | |
---|---|---|
committer | 2014-10-16 11:53:30 -0700 | |
commit | 19653d1d004610b4ba07ce563a5701164e120e45 (patch) | |
tree | 16519c940c8b52f5f596a8759207ee5f31062a69 /src/core | |
parent | c9df8ce8212448a9d33b57d266a0aef5c28a98e9 (diff) |
Implicit SkTextBlob bounds
Compute blob bounds when the client doesn't pass explicit run rects to
the builder. This allows us to remove a couple of internal workarounds.
R=reed@google.com,mtklein@google.com,bungeman@google.com
Review URL: https://codereview.chromium.org/654873003
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkCanvas.cpp | 4 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 4 | ||||
-rw-r--r-- | src/core/SkTextBlob.cpp | 46 |
3 files changed, 45 insertions, 9 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index c57add408f..709cb4c0be 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -2195,9 +2195,7 @@ void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPat void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { - // FIXME: temporarily disable quickreject for empty bounds, - // pending implicit blob bounds implementation. - if (!blob->bounds().isEmpty() && paint.canComputeFastBounds()) { + if (paint.canComputeFastBounds()) { SkRect storage; if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) { diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 45324b8cec..577ffa125e 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -456,10 +456,6 @@ private: Bounds bounds(const DrawTextBlob& op) const { SkRect dst = op.blob->bounds(); dst.offset(op.x, op.y); - // TODO: remove when implicit bounds are plumbed through - if (dst.isEmpty()) { - return fCurrentClipBounds; - } return this->adjustAndMap(dst, &op.paint); } diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp index b815c263a8..f298b547b7 100644 --- a/src/core/SkTextBlob.cpp +++ b/src/core/SkTextBlob.cpp @@ -318,7 +318,49 @@ void SkTextBlobBuilder::updateDeferredBounds() { return; } - // FIXME: measure the current run & union bounds + SkASSERT(fLastRun >= sizeof(SkTextBlob)); + SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + + fLastRun); + SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding()); + + SkRect runBounds = SkRect::MakeEmpty(); + if (SkTextBlob::kDefault_Positioning == run->positioning()) { + run->font().measureText(run->glyphBuffer(), + run->glyphCount() * sizeof(uint16_t), + &runBounds); + } else { + SkASSERT(SkTextBlob::kFull_Positioning == run->positioning() || + SkTextBlob::kHorizontal_Positioning == run->positioning()); + + SkAutoSTArray<16, SkRect> glyphBounds(run->glyphCount()); + run->font().getTextWidths(run->glyphBuffer(), + run->glyphCount() * sizeof(uint16_t), + NULL, + glyphBounds.get()); + + SkScalar* glyphOffset = run->posBuffer(); + for (unsigned i = 0; i < run->glyphCount(); ++i) { + if (SkTextBlob::kFull_Positioning == run->positioning()) { + // [ x, y, x, y... ] + glyphBounds[i].offset(glyphOffset[0], glyphOffset[1]); + SkASSERT(2 == SkTextBlob::ScalarsPerGlyph(run->positioning())); + glyphOffset += 2; + } else { + // [ x, x, x... ], const y applied by runBounds.offset(run->offset()) later. + glyphBounds[i].offset(glyphOffset[0], 0); + SkASSERT(1 == SkTextBlob::ScalarsPerGlyph(run->positioning())); + glyphOffset += 1; + } + + runBounds.join(glyphBounds[i]); + } + + SkASSERT((void*)glyphOffset <= SkTextBlob::RunRecord::Next(run)); + } + + runBounds.offset(run->offset()); + + fBounds.join(runBounds); fDeferredBounds = false; } @@ -399,7 +441,7 @@ void SkTextBlobBuilder::allocInternal(const SkPaint &font, SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding()); if (!this->mergeRun(font, positioning, count, offset)) { - updateDeferredBounds(); + this->updateDeferredBounds(); size_t runSize = SkTextBlob::RunRecord::StorageSize(count, positioning); this->reserve(runSize); |