/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkDebugCanvas.h"
#include "SkDevice.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkOSFile.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkStream.h"
#include "picture_utils.h"

__SK_FORCE_IMAGE_DECODER_LINKING;

static void usage() {
    SkDebugf("Usage: filter -i inFile [-o outFile] [--input-dir path] [--output-dir path]\n");
    SkDebugf("                        [-h|--help]\n\n");
    SkDebugf("    -i inFile  : file to filter.\n");
    SkDebugf("    -o outFile : result of filtering.\n");
    SkDebugf("    --input-dir : process all files in dir with .skp extension.\n");
    SkDebugf("    --output-dir : results of filtering the input dir.\n");
    SkDebugf("    -h|--help  : Show this help message.\n");
}

// Is the supplied paint simply a color?
static bool is_simple(const SkPaint& p) {
    return NULL == p.getPathEffect() &&
           NULL == p.getShader() &&
           NULL == p.getXfermode() &&
           NULL == p.getMaskFilter() &&
           NULL == p.getColorFilter() &&
           NULL == p.getRasterizer() &&
           NULL == p.getLooper() &&
           NULL == p.getImageFilter();
}


// Check for:
//    SAVE_LAYER
//        DRAW_BITMAP_RECT_TO_RECT
//    RESTORE
// where the saveLayer's color can be moved into the drawBitmapRect
static bool check_0(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE_LAYER != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+2 ||
        DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+2)->getType()) {
        return false;
    }

    SkSaveLayerCommand* saveLayer =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+1);

    const SkPaint* saveLayerPaint = saveLayer->paint();
    SkPaint* dbmrPaint = dbmr->paint();

    // For this optimization we only fold the saveLayer and drawBitmapRect
    // together if the saveLayer's draw is simple (i.e., no fancy effects)
    // and the only difference in the colors is their alpha value
    SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque
    SkColor dbmrColor = dbmrPaint->getColor() | 0xFF000000;       // force opaque

    // If either operation lacks a paint then the collapse is trivial
    return NULL == saveLayerPaint ||
           NULL == dbmrPaint ||
           (is_simple(*saveLayerPaint) && dbmrColor == layerColor);
}

// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer
// and restore
static void apply_0(SkDebugCanvas* canvas, int curCommand) {
    SkSaveLayerCommand* saveLayer =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
    const SkPaint* saveLayerPaint = saveLayer->paint();

    // if (NULL == saveLayerPaint) the dbmr's paint doesn't need to be changed
    if (saveLayerPaint) {
        SkDrawBitmapRectCommand* dbmr =
            (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+1);
        SkPaint* dbmrPaint = dbmr->paint();

        if (NULL == dbmrPaint) {
            // if the DBMR doesn't have a paint just use the saveLayer's
            dbmr->setPaint(*saveLayerPaint);
        } else if (saveLayerPaint) {
            // Both paints are present so their alphas need to be combined
            SkColor color = saveLayerPaint->getColor();
            int a0 = SkColorGetA(color);

            color = dbmrPaint->getColor();
            int a1 = SkColorGetA(color);

            int newA = SkMulDiv255Round(a0, a1);
            SkASSERT(newA <= 0xFF);

            SkColor newColor = SkColorSetA(color, newA);
            dbmrPaint->setColor(newColor);
        }
    }

    canvas->deleteDrawCommandAt(curCommand+2);  // restore
    canvas->deleteDrawCommandAt(curCommand);    // saveLayer
}

// Check for:
//    SAVE_LAYER
//        SAVE
//            CLIP_RECT
//            DRAW_BITMAP_RECT_TO_RECT
//        RESTORE
//    RESTORE
// where the saveLayer's color can be moved into the drawBitmapRect
static bool check_1(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE_LAYER != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+5 ||
        SAVE != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+3)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+4)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+5)->getType()) {
        return false;
    }

    SkSaveLayerCommand* saveLayer =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+3);

    const SkPaint* saveLayerPaint = saveLayer->paint();
    SkPaint* dbmrPaint = dbmr->paint();

    // For this optimization we only fold the saveLayer and drawBitmapRect
    // together if the saveLayer's draw is simple (i.e., no fancy effects) and
    // and the only difference in the colors is that the saveLayer's can have
    // an alpha while the drawBitmapRect's is opaque.
    // TODO: it should be possible to fold them together even if they both
    // have different non-255 alphas but this is low priority since we have
    // never seen that case
    // If either operation lacks a paint then the collapse is trivial
    SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque

    return NULL == saveLayerPaint ||
           NULL == dbmrPaint ||
           (is_simple(*saveLayerPaint) && dbmrPaint->getColor() == layerColor);
}

// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer
// and restore
static void apply_1(SkDebugCanvas* canvas, int curCommand) {
    SkSaveLayerCommand* saveLayer =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
    const SkPaint* saveLayerPaint = saveLayer->paint();

    // if (NULL == saveLayerPaint) the dbmr's paint doesn't need to be changed
    if (saveLayerPaint) {
        SkDrawBitmapRectCommand* dbmr =
            (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+3);
        SkPaint* dbmrPaint = dbmr->paint();

        if (NULL == dbmrPaint) {
            dbmr->setPaint(*saveLayerPaint);
        } else {
            SkColor newColor = SkColorSetA(dbmrPaint->getColor(),
                                           SkColorGetA(saveLayerPaint->getColor()));
            dbmrPaint->setColor(newColor);
        }
    }

    canvas->deleteDrawCommandAt(curCommand+5);    // restore
    canvas->deleteDrawCommandAt(curCommand);      // saveLayer
}

// Check for:
//    SAVE
//        CLIP_RECT
//        DRAW_RECT
//    RESTORE
// where the rect is entirely within the clip and the clip is an intersect
static bool check_2(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+4 ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        DRAW_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
        return false;
    }

    SkClipRectCommand* cr =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawRectCommand* dr =
        (SkDrawRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    if (SkRegion::kIntersect_Op != cr->op()) {
        return false;
    }

    return cr->rect().contains(dr->rect());
}

// Remove everything but the drawRect
static void apply_2(SkDebugCanvas* canvas, int curCommand) {
    canvas->deleteDrawCommandAt(curCommand+3);   // restore
    // drawRect
    canvas->deleteDrawCommandAt(curCommand+1);   // clipRect
    canvas->deleteDrawCommandAt(curCommand);     // save
}

// Check for:
//    SAVE
//        CLIP_RRECT
//        DRAW_RECT
//    RESTORE
// where the rect entirely encloses the clip
static bool check_3(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+4 ||
        CLIP_RRECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        DRAW_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
        return false;
    }

    SkClipRRectCommand* crr =
        (SkClipRRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawRectCommand* dr  =
        (SkDrawRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    if (SkRegion::kIntersect_Op != crr->op()) {
        return false;
    }

    return dr->rect().contains(crr->rrect().rect());
}

// Replace everything with a drawRRect with the paint from the drawRect
// and the AA settings from the clipRRect
static void apply_3(SkDebugCanvas* canvas, int curCommand) {

    canvas->deleteDrawCommandAt(curCommand+3);    // restore

    SkClipRRectCommand* crr =
        (SkClipRRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawRectCommand* dr  =
        (SkDrawRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    // TODO: could skip paint re-creation if the AA settings already match
    SkPaint newPaint = dr->paint();
    newPaint.setAntiAlias(crr->doAA());
    SkDrawRRectCommand* drr = new SkDrawRRectCommand(crr->rrect(), newPaint);
    canvas->setDrawCommandAt(curCommand+2, drr);

    canvas->deleteDrawCommandAt(curCommand+1);    // clipRRect
    canvas->deleteDrawCommandAt(curCommand);      // save
}

// Check for:
//    SAVE
//        CLIP_RECT
//        DRAW_BITMAP_RECT_TO_RECT
//    RESTORE
// where the rect and drawBitmapRect dst exactly match
static bool check_4(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+4 ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
        return false;
    }

    SkClipRectCommand* cr =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawBitmapRectCommand* dbmr  =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    if (SkRegion::kIntersect_Op != cr->op()) {
        return false;
    }

    return dbmr->dstRect() == cr->rect();
}

// Remove everything but the drawBitmapRect
static void apply_4(SkDebugCanvas* canvas, int curCommand) {
    canvas->deleteDrawCommandAt(curCommand+3);    // restore
    // drawBitmapRectToRect
    canvas->deleteDrawCommandAt(curCommand+1);    // clipRect
    canvas->deleteDrawCommandAt(curCommand);      // save
}

// Check for:
//    TRANSLATE
// where the translate is zero
static bool check_5(SkDebugCanvas* canvas, int curCommand) {
    if (TRANSLATE != canvas->getDrawCommandAt(curCommand)->getType()) {
        return false;
    }

    SkTranslateCommand* t =
        (SkTranslateCommand*) canvas->getDrawCommandAt(curCommand);

    return 0 == t->x() && 0 == t->y();
}

// Just remove the translate
static void apply_5(SkDebugCanvas* canvas, int curCommand) {
    canvas->deleteDrawCommandAt(curCommand);    // translate
}

// Check for:
//    SCALE
// where the scale is 1,1
static bool check_6(SkDebugCanvas* canvas, int curCommand) {
    if (SCALE != canvas->getDrawCommandAt(curCommand)->getType()) {
        return false;
    }

    SkScaleCommand* s = (SkScaleCommand*) canvas->getDrawCommandAt(curCommand);

    return SK_Scalar1 == s->x() && SK_Scalar1 == s->y();
}

// Just remove the scale
static void apply_6(SkDebugCanvas* canvas, int curCommand) {
    canvas->deleteDrawCommandAt(curCommand);   // scale
}

// 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(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+13 ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        SAVE_LAYER != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        SAVE != canvas->getDrawCommandAt(curCommand+3)->getType() ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+4)->getType() ||
        SAVE_LAYER != canvas->getDrawCommandAt(curCommand+5)->getType() ||
        SAVE != canvas->getDrawCommandAt(curCommand+6)->getType() ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+7)->getType() ||
        DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+8)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+9)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+10)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+11)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+12)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+13)->getType()) {
        return false;
    }

    SkClipRectCommand* clip0 =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkSaveLayerCommand* saveLayer0 =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+2);
    SkClipRectCommand* clip1 =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+4);
    SkSaveLayerCommand* saveLayer1 =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+5);
    SkClipRectCommand* clip2 =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+7);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(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 ((saveLayerPaint0 && !is_simple(*saveLayerPaint0)) ||
        (saveLayerPaint1 && !is_simple(*saveLayerPaint1))) {
        return false;
    }

    SkPaint* dbmrPaint = dbmr->paint();

    if (NULL == dbmrPaint) {
        return true;
    }

    if (saveLayerPaint0) {
        SkColor layerColor0 = saveLayerPaint0->getColor() | 0xFF000000; // force opaque
        if (dbmrPaint->getColor() != layerColor0) {
            return false;
        }
    }

    if (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(SkDebugCanvas* canvas, int curCommand) {
    SkSaveLayerCommand* saveLayer0 =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+2);
    SkSaveLayerCommand* saveLayer1 =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+5);
    SkClipRectCommand* clip2 =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+7);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+8);

    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 (saveLayerPaint0) {
        color = saveLayerPaint0->getColor();
        a0 = SkColorGetA(color);
    } else {
        a0 = 0xFF;
    }

    const SkPaint* saveLayerPaint1 = saveLayer1->paint();
    if (saveLayerPaint1) {
        color = saveLayerPaint1->getColor();
        a1 = SkColorGetA(color);
    } else {
        a1 = 0xFF;
    }

    int newA = SkMulDiv255Round(a0, a1);
    SkASSERT(newA <= 0xFF);

    SkPaint* dbmrPaint = dbmr->paint();

    if (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
    canvas->deleteDrawCommandAt(curCommand+13);   // restore
    canvas->deleteDrawCommandAt(curCommand+12);   // restore
    canvas->deleteDrawCommandAt(curCommand+11);   // restore
    canvas->deleteDrawCommandAt(curCommand+10);   // restore
    canvas->deleteDrawCommandAt(curCommand+9);    // restore
    canvas->deleteDrawCommandAt(curCommand+7);    // clipRect
    canvas->deleteDrawCommandAt(curCommand+6);    // save
    canvas->deleteDrawCommandAt(curCommand+5);    // saveLayer
    canvas->deleteDrawCommandAt(curCommand+4);    // clipRect
    canvas->deleteDrawCommandAt(curCommand+3);    // save
    canvas->deleteDrawCommandAt(curCommand+2);    // saveLayer
    canvas->deleteDrawCommandAt(curCommand+1);    // clipRect
    canvas->deleteDrawCommandAt(curCommand);      // save
}

// Check for:
//    SAVE
//       CLIP_RECT
//       DRAWBITMAPRECTTORECT
//    RESTORE
// where:
//      the drawBitmapRectToRect is a 1-1 copy from src to dest
//      the clip rect is BW and a subset of the drawBitmapRectToRect's dest rect
static bool check_8(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+4 ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
        return false;
    }

    SkClipRectCommand* clip =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    if (clip->doAA() || SkRegion::kIntersect_Op != clip->op()) {
        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(clip->rect())) {
        return false;
    }

    return true;
}

// Fold the clipRect into the drawBitmapRectToRect's src and dest rects
static void apply_8(SkDebugCanvas* canvas, int curCommand) {
    SkClipRectCommand* clip =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    SkScalar newSrcLeft, newSrcTop;

    if (dbmr->srcRect()) {
        newSrcLeft = dbmr->srcRect()->fLeft + clip->rect().fLeft - dbmr->dstRect().fLeft;
        newSrcTop  = dbmr->srcRect()->fTop + clip->rect().fTop - dbmr->dstRect().fTop;
    } else {
        newSrcLeft = clip->rect().fLeft - dbmr->dstRect().fLeft;
        newSrcTop  = clip->rect().fTop - dbmr->dstRect().fTop;
    }

    SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop,
                                     clip->rect().width(), clip->rect().height());

    dbmr->setSrcRect(newSrc);
    dbmr->setDstRect(clip->rect());

    // remove everything except the drawbitmaprect
    canvas->deleteDrawCommandAt(curCommand+3);
    canvas->deleteDrawCommandAt(curCommand+1);
    canvas->deleteDrawCommandAt(curCommand);
}

// Check for:
//  SAVE
//    CLIP_RECT
//    DRAWBITMAPRECTTORECT
//  RESTORE
// where:
//      clipRect is BW and encloses the DBMR2R's dest rect
static bool check_9(SkDebugCanvas* canvas, int curCommand) {
    if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
        canvas->getSize() <= curCommand+4 ||
        CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
        DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
        RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
        return false;
    }

    SkClipRectCommand* clip =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);

    if (clip->doAA() || SkRegion::kIntersect_Op != clip->op()) {
        return false;
    }

    if (!clip->rect().contains(dbmr->dstRect())) {
        return false;
    }

    return true;
}

// remove everything except the drawbitmaprect
static void apply_9(SkDebugCanvas* canvas, int curCommand) {
    canvas->deleteDrawCommandAt(curCommand+3);   // restore
    // drawBitmapRectToRect
    canvas->deleteDrawCommandAt(curCommand+1);   // clipRect
    canvas->deleteDrawCommandAt(curCommand);     // save
}

typedef bool (*PFCheck)(SkDebugCanvas* canvas, int curCommand);
typedef void (*PFApply)(SkDebugCanvas* canvas, int curCommand);

struct OptTableEntry {
    PFCheck fCheck;
    PFApply fApply;
    int fNumTimesApplied;
} gOptTable[] = {
    { check_0, apply_0, 0 },
    { check_1, apply_1, 0 },
    { check_2, apply_2, 0 },
    { check_3, apply_3, 0 },
    { check_4, apply_4, 0 },
    { check_5, apply_5, 0 },
    { check_6, apply_6, 0 },
    { check_7, apply_7, 0 },
    { check_8, apply_8, 0 },
    { check_9, apply_9, 0 },
};


static int filter_picture(const SkString& inFile, const SkString& outFile) {
    SkAutoTUnref<SkPicture> inPicture;

    SkFILEStream inStream(inFile.c_str());
    if (inStream.isValid()) {
        inPicture.reset(SkPicture::CreateFromStream(&inStream));
    }

    if (NULL == inPicture.get()) {
        SkDebugf("Could not read file %s\n", inFile.c_str());
        return -1;
    }

    int localCount[SK_ARRAY_COUNT(gOptTable)];

    memset(localCount, 0, sizeof(localCount));

    SkDebugCanvas debugCanvas(SkScalarCeilToInt(inPicture->cullRect().width()), 
                              SkScalarCeilToInt(inPicture->cullRect().height()));
    inPicture->playback(&debugCanvas);

    // delete the initial save and restore since replaying the commands will
    // re-add them
    if (debugCanvas.getSize() > 1) {
        debugCanvas.deleteDrawCommandAt(0);
        debugCanvas.deleteDrawCommandAt(debugCanvas.getSize()-1);
    }

    bool changed = true;
    int numBefore = debugCanvas.getSize();

    while (changed) {
        changed = false;
        for (int i = 0; i < debugCanvas.getSize(); ++i) {
            for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) {
                if ((*gOptTable[opt].fCheck)(&debugCanvas, i)) {
                    (*gOptTable[opt].fApply)(&debugCanvas, i);

                    ++gOptTable[opt].fNumTimesApplied;
                    ++localCount[opt];

                    if (debugCanvas.getSize() == i) {
                        // the optimization removed all the remaining operations
                        break;
                    }

                    opt = 0;          // try all the opts all over again
                    changed = true;
                }
            }
        }
    }

    int numAfter = debugCanvas.getSize();

    if (!outFile.isEmpty()) {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(inPicture->cullRect().width(), 
                                                   inPicture->cullRect().height(), 
                                                   NULL, 0);
        debugCanvas.draw(canvas);
        SkAutoTUnref<SkPicture> outPicture(recorder.endRecording());

        SkFILEWStream outStream(outFile.c_str());

        outPicture->serialize(&outStream);
    }

    bool someOptFired = false;
    for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) {
        if (0 != localCount[opt]) {
            SkDebugf("%d: %d ", opt, localCount[opt]);
            someOptFired = true;
        }
    }

    if (!someOptFired) {
        SkDebugf("No opts fired\n");
    } else {
        SkDebugf("\t before: %d after: %d delta: %d\n",
                 numBefore, numAfter, numBefore-numAfter);
    }

    return 0;
}

// This function is not marked as 'static' so it can be referenced externally
// in the iOS build.
int tool_main(int argc, char** argv); // suppress a warning on mac

int tool_main(int argc, char** argv) {
#if SK_ENABLE_INST_COUNT
    gPrintInstCount = true;
#endif

    SkGraphics::Init();

    if (argc < 3) {
        usage();
        return -1;
    }

    SkString inFile, outFile, inDir, outDir;

    char* const* stop = argv + argc;
    for (++argv; argv < stop; ++argv) {
        if (strcmp(*argv, "-i") == 0) {
            argv++;
            if (argv < stop && **argv) {
                inFile.set(*argv);
            } else {
                SkDebugf("missing arg for -i\n");
                usage();
                return -1;
            }
        } else if (strcmp(*argv, "--input-dir") == 0) {
            argv++;
            if (argv < stop && **argv) {
                inDir.set(*argv);
            } else {
                SkDebugf("missing arg for --input-dir\n");
                usage();
                return -1;
            }
        } else if (strcmp(*argv, "--output-dir") == 0) {
            argv++;
            if (argv < stop && **argv) {
                outDir.set(*argv);
            } else {
                SkDebugf("missing arg for --output-dir\n");
                usage();
                return -1;
            }
        } else if (strcmp(*argv, "-o") == 0) {
            argv++;
            if (argv < stop && **argv) {
                outFile.set(*argv);
            } else {
                SkDebugf("missing arg for -o\n");
                usage();
                return -1;
            }
        } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) {
            usage();
            return 0;
        } else {
            SkDebugf("unknown arg %s\n", *argv);
            usage();
            return -1;
        }
    }

    SkOSFile::Iter iter(inDir.c_str(), "skp");

    SkString inputFilename, outputFilename;
    if (iter.next(&inputFilename)) {

        do {
            inFile = SkOSPath::Join(inDir.c_str(), inputFilename.c_str());
            if (!outDir.isEmpty()) {
                outFile = SkOSPath::Join(outDir.c_str(), inputFilename.c_str());
            }
            SkDebugf("Executing %s\n", inputFilename.c_str());
            filter_picture(inFile, outFile);
        } while(iter.next(&inputFilename));

    } else if (!inFile.isEmpty()) {
        filter_picture(inFile, outFile);
    } else {
        usage();
        return -1;
    }

    for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) {
        SkDebugf("opt %d: %d\n", opt, gOptTable[opt].fNumTimesApplied);
    }

    SkGraphics::Term();
    return 0;
}

#if !defined SK_BUILD_FOR_IOS
int main(int argc, char * const argv[]) {
    return tool_main(argc, (char**) argv);
}
#endif
