New filter targeted at desk_googlespreadsheet overdraw issues
authorrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 28 Mar 2013 12:25:25 +0000 (12:25 +0000)
committerrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 28 Mar 2013 12:25:25 +0000 (12:25 +0000)
https://codereview.chromium.org/12918029/

git-svn-id: http://skia.googlecode.com/svn/trunk@8424 2bbb7eff-a529-9590-31e7-b0007b416f81

debugger/SkDrawCommand.h
tools/filtermain.cpp

index 65e1f0d..02a4afe 100644 (file)
@@ -200,6 +200,8 @@ public:
     virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
     virtual const SkBitmap* getBitmap() const SK_OVERRIDE;
 
+    const SkBitmap& bitmap() const { return fBitmap; }
+
     // The non-const 'paint' method allows modification of this object's
     // SkPaint. For this reason the ctor and setPaint method make a local copy.
     // The 'fPaintPtr' member acts a signal that the local SkPaint is valid
@@ -212,6 +214,9 @@ public:
     const SkRect* srcRect() const { return fSrc.isEmpty() ? NULL : &fSrc; }
     const SkRect& dstRect() const { return fDst; }
 
+    void setSrcRect(const SkRect& src) { fSrc = src; }
+    void setDstRect(const SkRect& dst) { fDst = dst; }
+
 private:
     SkBitmap fBitmap;
     SkRect   fSrc;
index 14eafdc..aa7afa0 100644 (file)
@@ -320,6 +320,193 @@ static void apply_6(SkTDArray<SkDrawCommand*>& commands, int curCommand) {
     s->setVisible(false);
 }
 
+// Check for:
+//  SAVE
+//      CLIP_RECT
+//      SAVE_LAYER
+//          SAVE
+//              CLIP_RECT
+//              SAVE_LAYER
+//                  SAVE
+//                      CLIP_RECT
+//                      DRAWBITMAPRECTTORECT
+//                  RESTORE
+//              RESTORE
+//          RESTORE
+//      RESTORE
+//  RESTORE
+// where:
+//      all the clipRect's are BW, nested, intersections
+//      the drawBitmapRectToRect is a 1-1 copy from src to dest
+//      the last (smallest) clip rect is a subset of the drawBitmapRectToRect's dest rect
+//      all the saveLayer's paints can be rolled into the drawBitmapRectToRect's paint
+// This pattern is used by Google spreadsheet when drawing the toolbar buttons
+static bool check_7(const SkTDArray<SkDrawCommand*>& commands, int curCommand) {
+    if (SAVE != commands[curCommand]->getType() ||
+        commands.count() <= curCommand+13 ||
+        CLIP_RECT != commands[curCommand+1]->getType() ||
+        SAVE_LAYER != commands[curCommand+2]->getType() ||
+        SAVE != commands[curCommand+3]->getType() ||
+        CLIP_RECT != commands[curCommand+4]->getType() ||
+        SAVE_LAYER != commands[curCommand+5]->getType() ||
+        SAVE != commands[curCommand+6]->getType() ||
+        CLIP_RECT != commands[curCommand+7]->getType() ||
+        DRAW_BITMAP_RECT_TO_RECT != commands[curCommand+8]->getType() ||
+        RESTORE != commands[curCommand+9]->getType() ||
+        RESTORE != commands[curCommand+10]->getType() ||
+        RESTORE != commands[curCommand+11]->getType() ||
+        RESTORE != commands[curCommand+12]->getType() ||
+        RESTORE != commands[curCommand+13]->getType())
+        return false;
+
+    ClipRect* clip0 = (ClipRect*) commands[curCommand+1];
+    SaveLayer* saveLayer0 = (SaveLayer*) commands[curCommand+2];
+    ClipRect* clip1 = (ClipRect*) commands[curCommand+4];
+    SaveLayer* saveLayer1 = (SaveLayer*) commands[curCommand+5];
+    ClipRect* clip2 = (ClipRect*) commands[curCommand+7];
+    DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+8];
+
+    if (clip0->doAA() || clip1->doAA() || clip2->doAA()) {
+        return false;
+    }
+
+    if (SkRegion::kIntersect_Op != clip0->op() ||
+        SkRegion::kIntersect_Op != clip1->op() ||
+        SkRegion::kIntersect_Op != clip2->op()) {
+        return false;
+    }
+
+    if (!clip0->rect().contains(clip1->rect()) || 
+        !clip1->rect().contains(clip2->rect())) {
+        return false;
+    }
+
+    // The src->dest mapping needs to be 1-to-1
+    if (NULL == dbmr->srcRect()) {
+        if (dbmr->bitmap().width() != dbmr->dstRect().width() ||
+            dbmr->bitmap().height() != dbmr->dstRect().height()) {
+            return false;
+        }
+    } else {
+        if (dbmr->srcRect()->width() != dbmr->dstRect().width() ||
+            dbmr->srcRect()->height() != dbmr->dstRect().height()) {
+            return false;
+        }
+    }
+
+    if (!dbmr->dstRect().contains(clip2->rect())) {
+        return false;
+    }
+
+    const SkPaint* saveLayerPaint0 = saveLayer0->paint();
+    const SkPaint* saveLayerPaint1 = saveLayer1->paint();
+
+    if ((NULL != saveLayerPaint0 && !is_simple(*saveLayerPaint0)) ||
+        (NULL != saveLayerPaint1 && !is_simple(*saveLayerPaint1))) {
+        return false;
+    }
+
+    SkPaint* dbmrPaint = dbmr->paint();
+
+    if (NULL == dbmrPaint) {
+        return true;    
+    }
+    
+    if (NULL != saveLayerPaint0) {
+        SkColor layerColor0 = saveLayerPaint0->getColor() | 0xFF000000; // force opaque
+        if (dbmrPaint->getColor() != layerColor0) {
+            return false;
+        }
+    }
+
+    if (NULL != saveLayerPaint1) {
+        SkColor layerColor1 = saveLayerPaint1->getColor() | 0xFF000000; // force opaque
+        if (dbmrPaint->getColor() != layerColor1) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Reduce to a single drawBitmapRectToRect call by folding the clipRect's into
+// the src and dst Rects and the saveLayer paints into the drawBitmapRectToRect's
+// paint.
+static void apply_7(SkTDArray<SkDrawCommand*>& commands, int curCommand) {
+    Save* save0 = (Save*) commands[curCommand];
+    ClipRect* clip0 = (ClipRect*) commands[curCommand+1];
+    SaveLayer* saveLayer0 = (SaveLayer*) commands[curCommand+2];
+    Save* save1 = (Save*) commands[curCommand+3];
+    ClipRect* clip1 = (ClipRect*) commands[curCommand+4];
+    SaveLayer* saveLayer1 = (SaveLayer*) commands[curCommand+5];
+    Save* save2 = (Save*) commands[curCommand+6];
+    ClipRect* clip2 = (ClipRect*) commands[curCommand+7];
+    DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+8];
+    Restore* restore0 = (Restore*) commands[curCommand+9];
+    Restore* restore1 = (Restore*) commands[curCommand+10];
+    Restore* restore2 = (Restore*) commands[curCommand+11];
+    Restore* restore3 = (Restore*) commands[curCommand+12];
+    Restore* restore4 = (Restore*) commands[curCommand+13];
+
+    SkScalar newSrcLeft = dbmr->srcRect()->fLeft + clip2->rect().fLeft - dbmr->dstRect().fLeft;
+    SkScalar newSrcTop = dbmr->srcRect()->fTop + clip2->rect().fTop - dbmr->dstRect().fTop;
+
+    SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop, 
+                                     clip2->rect().width(), clip2->rect().height());
+
+    dbmr->setSrcRect(newSrc);
+    dbmr->setDstRect(clip2->rect());
+
+    SkColor color = 0xFF000000;
+    int a0, a1;
+
+    const SkPaint* saveLayerPaint0 = saveLayer0->paint();
+    if (NULL != saveLayerPaint0) {
+        color = saveLayerPaint0->getColor();
+        a0 = SkColorGetA(color);
+    } else {
+        a0 = 0xFF;
+    }
+
+    const SkPaint* saveLayerPaint1 = saveLayer1->paint();
+    if (NULL != saveLayerPaint1) {
+        color = saveLayerPaint1->getColor();
+        a1 = SkColorGetA(color);
+    } else {
+        a1 = 0xFF;
+    }
+
+    int newA = (a0 * a1) / 255;
+    SkASSERT(newA <= 0xFF);
+
+    SkPaint* dbmrPaint = dbmr->paint();
+
+    if (NULL != dbmrPaint) {
+        SkColor newColor = SkColorSetA(dbmrPaint->getColor(), newA);
+        dbmrPaint->setColor(newColor);
+    } else {
+        SkColor newColor = SkColorSetA(color, newA);
+
+        SkPaint newPaint;
+        newPaint.setColor(newColor);
+        dbmr->setPaint(newPaint);
+    }
+
+    // remove everything except the drawbitmaprect
+    save0->setVisible(false);
+    clip0->setVisible(false);
+    saveLayer0->setVisible(false);
+    save1->setVisible(false);
+    clip1->setVisible(false);
+    saveLayer1->setVisible(false);
+    save2->setVisible(false);
+    clip2->setVisible(false);
+    restore0->setVisible(false);
+    restore1->setVisible(false);
+    restore2->setVisible(false);
+    restore3->setVisible(false);
+    restore4->setVisible(false);
+}
 
 typedef bool (*PFCheck)(const SkTDArray<SkDrawCommand*>& commands, int curCommand);
 typedef void (*PFApply)(SkTDArray<SkDrawCommand*>& commands, int curCommand);
@@ -336,6 +523,7 @@ struct OptTableEntry {
     { check_4, apply_4, 0 },
     { check_5, apply_5, 0 },
     { check_6, apply_6, 0 },
+    { check_7, apply_7, 0 },
 };
 
 static int filter_picture(const SkString& inFile, const SkString& outFile) {