aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2014-10-16 11:53:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-16 11:53:30 -0700
commit19653d1d004610b4ba07ce563a5701164e120e45 (patch)
tree16519c940c8b52f5f596a8759207ee5f31062a69 /src
parentc9df8ce8212448a9d33b57d266a0aef5c28a98e9 (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')
-rw-r--r--src/core/SkCanvas.cpp4
-rw-r--r--src/core/SkRecordDraw.cpp4
-rw-r--r--src/core/SkTextBlob.cpp46
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);