Implicit SkTextBlob bounds
authorfmalita <fmalita@chromium.org>
Thu, 16 Oct 2014 18:53:30 +0000 (11:53 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 16 Oct 2014 18:53:30 +0000 (11:53 -0700)
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

expectations/gm/ignored-tests.txt
src/core/SkCanvas.cpp
src/core/SkRecordDraw.cpp
src/core/SkTextBlob.cpp

index 5793ba2..1ae107c 100644 (file)
@@ -54,3 +54,6 @@ megalooper_0x0
 megalooper_1x4
 megalooper_4x1
 imagefiltersbase
+
+# fmalita to rebaseline after adding implicit bounds support
+textblob
index c57add4..709cb4c 100644 (file)
@@ -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))) {
index 45324b8..577ffa1 100644 (file)
@@ -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);
     }
 
index b815c26..f298b54 100644 (file)
@@ -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);