Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkBBoxRecord.cpp
index 0dadb5c..69139ad 100644 (file)
@@ -7,6 +7,11 @@
  */
 
 #include "SkBBoxRecord.h"
+#include "SkPatchUtils.h"
+
+SkBBoxRecord::~SkBBoxRecord() {
+    fSaveStack.deleteAll();
+}
 
 void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
     if (this->transformBounds(rect, &paint)) {
@@ -165,6 +170,18 @@ void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
     }
 }
 
+// Hack to work-around https://code.google.com/p/chromium/issues/detail?id=373785
+// This logic assums that 'pad' is enough to add to the left and right to account for
+// big glyphs. For the font in question (a logo font) the glyphs is much wider than just
+// the pointsize (approx 3x wider).
+// As a temp work-around, we scale-up pad.
+// A more correct fix might be to add fontmetrics.fMaxX, but we don't have that value in hand
+// at the moment, and (possibly) the value in the font may not be accurate (but who knows).
+//
+static SkScalar hack_373785_amend_pad(SkScalar pad) {
+    return pad * 4;
+}
+
 void SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
                                  const SkPaint& paint) {
     SkRect bbox;
@@ -176,6 +193,7 @@ void SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPo
 
     // pad on left and right by half of max vertical glyph extents
     SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
+    pad = hack_373785_amend_pad(pad);
     bbox.fLeft += pad;
     bbox.fRight -= pad;
 
@@ -212,6 +230,7 @@ void SkBBoxRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkS
     }
 
     // pad horizontally by max glyph height
+    pad = hack_373785_amend_pad(pad);
     bbox.fLeft  += pad;
     bbox.fRight -= pad;
 
@@ -266,13 +285,50 @@ void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
     }
 }
 
-void SkBBoxRecord::drawPicture(SkPicture& picture) {
-    if (picture.width() > 0 && picture.height() > 0 &&
-        this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
-        INHERITED::drawPicture(picture);
+void SkBBoxRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+                               const SkPoint texCoords[4], SkXfermode* xmode,
+                               const SkPaint& paint) {
+    SkRect bbox;
+    bbox.set(cubics, SkPatchUtils::kNumCtrlPts);
+    if (this->transformBounds(bbox, &paint)) {
+        INHERITED::onDrawPatch(cubics, colors, texCoords, xmode, paint);
     }
 }
 
+void SkBBoxRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
+                                 const SkPaint* paint) {
+    SkRect bounds = SkRect::MakeWH(SkIntToScalar(picture->width()),
+                                   SkIntToScalar(picture->height()));
+    // todo: wonder if we should allow passing an optional matrix to transformBounds so we don't
+    // end up transforming the rect twice.
+    if (matrix) {
+        matrix->mapRect(&bounds);
+    }
+    if (this->transformBounds(bounds, paint)) {
+        this->INHERITED::onDrawPicture(picture, matrix, paint);
+    }
+}
+
+void SkBBoxRecord::willSave() {
+    fSaveStack.push(NULL);
+    this->INHERITED::willSave();
+}
+
+SkCanvas::SaveLayerStrategy SkBBoxRecord::willSaveLayer(const SkRect* bounds,
+                                                        const SkPaint* paint,
+                                                        SaveFlags flags) {
+    // Image filters can affect the effective bounds of primitives drawn inside saveLayer().
+    // Copy the paint so we can compute the modified bounds in transformBounds().
+    fSaveStack.push(paint && paint->getImageFilter() ? new SkPaint(*paint) : NULL);
+    return this->INHERITED::willSaveLayer(bounds, paint, flags);
+}
+
+void SkBBoxRecord::willRestore() {
+    delete fSaveStack.top();
+    fSaveStack.pop();
+    this->INHERITED::willRestore();
+}
+
 bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
     SkRect outBounds = bounds;
     outBounds.sort();
@@ -291,6 +347,14 @@ bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
         }
     }
 
+    for (int i = fSaveStack.count() - 1; i >= 0; --i) {
+        const SkPaint* paint = fSaveStack.getAt(i);
+        if (paint && paint->canComputeFastBounds()) {
+            SkRect temp;
+            outBounds = paint->computeFastBounds(outBounds, &temp);
+        }
+    }
+
     if (!outBounds.isEmpty() && !this->quickReject(outBounds)) {
         this->getTotalMatrix().mapRect(&outBounds);
         this->handleBBox(outBounds);