
/*
 * 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 "SkDrawCommand.h"
#include "SkObjectParser.h"

#include "SkTextBlob.h"

// TODO(chudy): Refactor into non subclass model.

SkDrawCommand::SkDrawCommand(DrawType type)
    : fDrawType(type)
    , fOffset(0)
    , fVisible(true) {
}

SkDrawCommand::~SkDrawCommand() {
    fInfo.deleteAll();
}

const char* SkDrawCommand::GetCommandString(DrawType type) {
    switch (type) {
        case UNUSED: SkDEBUGFAIL("DrawType UNUSED\n"); break;
        case DRAW_CLEAR: return "Clear";
        case CLIP_PATH: return "Clip Path";
        case CLIP_REGION: return "Clip Region";
        case CLIP_RECT: return "Clip Rect";
        case CLIP_RRECT: return "Clip RRect";
        case CONCAT: return "Concat";
        case DRAW_BITMAP: return "Draw Bitmap";
        case DRAW_BITMAP_MATRIX: return "Draw Bitmap Matrix";
        case DRAW_BITMAP_NINE: return "Draw Bitmap Nine";
        case DRAW_BITMAP_RECT_TO_RECT: return "Draw Bitmap Rect";
        case DRAW_DATA: return "Draw Data";
        case DRAW_OVAL: return "Draw Oval";
        case DRAW_PAINT: return "Draw Paint";
        case DRAW_PATH: return "Draw Path";
        case DRAW_PICTURE: return "Draw Picture";
        case DRAW_POINTS: return "Draw Points";
        case DRAW_POS_TEXT: return "Draw Pos Text";
        case DRAW_POS_TEXT_H: return "Draw Pos Text H";
        case DRAW_RECT: return "Draw Rect";
        case DRAW_RRECT: return "Draw RRect";
        case DRAW_SPRITE: return "Draw Sprite";
        case DRAW_TEXT: return "Draw Text";
        case DRAW_TEXT_BLOB: return "Draw Text Blob";
        case DRAW_TEXT_ON_PATH: return "Draw Text On Path";
        case DRAW_VERTICES: return "Draw Vertices";
        case RESTORE: return "Restore";
        case ROTATE: return "Rotate";
        case SAVE: return "Save";
        case SAVE_LAYER: return "Save Layer";
        case SCALE: return "Scale";
        case SET_MATRIX: return "Set Matrix";
        case SKEW: return "Skew";
        case TRANSLATE: return "Translate";
        case NOOP: return "NoOp";
        case BEGIN_COMMENT_GROUP: return "BeginCommentGroup";
        case COMMENT: return "Comment";
        case END_COMMENT_GROUP: return "EndCommentGroup";
        case DRAW_DRRECT: return "Draw DRRect";
        case PUSH_CULL: return "PushCull";
        case POP_CULL: return "PopCull";
        default:
            SkDebugf("DrawType error 0x%08x\n", type);
            SkASSERT(0);
            break;
    }
    SkDEBUGFAIL("DrawType UNUSED\n");
    return NULL;
}

SkString SkDrawCommand::toString() const {
    return SkString(GetCommandString(fDrawType));
}

SkClearCommand::SkClearCommand(SkColor color) : INHERITED(DRAW_CLEAR) {
    fColor = color;
    fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
}

void SkClearCommand::execute(SkCanvas* canvas) const {
    canvas->clear(fColor);
}

namespace {

void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
    const SkISize& size = canvas->getDeviceSize();

    static const SkScalar kInsetFrac = 0.9f; // Leave a border around object

    canvas->translate(size.fWidth/2.0f, size.fHeight/2.0f);
    if (bounds.width() > bounds.height()) {
        canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.width()),
                      SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.width()));
    } else {
        canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.height()),
                      SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.height()));
    }
    canvas->translate(-bounds.centerX(), -bounds.centerY());
}


void render_path(SkCanvas* canvas, const SkPath& path) {
    canvas->clear(0xFFFFFFFF);
    canvas->save();

    const SkRect& bounds = path.getBounds();

    xlate_and_scale_to_bounds(canvas, bounds);

    SkPaint p;
    p.setColor(SK_ColorBLACK);
    p.setStyle(SkPaint::kStroke_Style);

    canvas->drawPath(path, p);
    canvas->restore();
}

void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = NULL) {
    const SkISize& size = canvas->getDeviceSize();

    SkScalar xScale = SkIntToScalar(size.fWidth-2) / input.width();
    SkScalar yScale = SkIntToScalar(size.fHeight-2) / input.height();

    if (input.width() > input.height()) {
        yScale *= input.height() / (float) input.width();
    } else {
        xScale *= input.width() / (float) input.height();
    }

    SkRect dst = SkRect::MakeXYWH(SK_Scalar1, SK_Scalar1,
                                  xScale * input.width(),
                                  yScale * input.height());

    canvas->clear(0xFFFFFFFF);
    canvas->drawBitmapRect(input, NULL, dst);

    if (srcRect) {
        SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
                                    srcRect->fTop * yScale + SK_Scalar1,
                                    srcRect->fRight * xScale + SK_Scalar1,
                                    srcRect->fBottom * yScale + SK_Scalar1);
        SkPaint p;
        p.setColor(SK_ColorRED);
        p.setStyle(SkPaint::kStroke_Style);

        canvas->drawRect(r, p);
    }
}

void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
    canvas->clear(0xFFFFFFFF);
    canvas->save();

    const SkRect& bounds = rrect.getBounds();

    xlate_and_scale_to_bounds(canvas, bounds);

    SkPaint p;
    p.setColor(SK_ColorBLACK);
    p.setStyle(SkPaint::kStroke_Style);

    canvas->drawRRect(rrect, p);
    canvas->restore();
}

void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
    canvas->clear(0xFFFFFFFF);
    canvas->save();

    const SkRect& bounds = outer.getBounds();

    xlate_and_scale_to_bounds(canvas, bounds);

    SkPaint p;
    p.setColor(SK_ColorBLACK);
    p.setStyle(SkPaint::kStroke_Style);

    canvas->drawDRRect(outer, inner, p);
    canvas->restore();
}

};


SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkRegion::Op op, bool doAA)
    : INHERITED(CLIP_PATH) {
    fPath = path;
    fOp = op;
    fDoAA = doAA;

    fInfo.push(SkObjectParser::PathToString(path));
    fInfo.push(SkObjectParser::RegionOpToString(op));
    fInfo.push(SkObjectParser::BoolToString(doAA));
}

void SkClipPathCommand::execute(SkCanvas* canvas) const {
    canvas->clipPath(fPath, fOp, fDoAA);
}

bool SkClipPathCommand::render(SkCanvas* canvas) const {
    render_path(canvas, fPath);
    return true;
}

SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkRegion::Op op)
    : INHERITED(CLIP_REGION) {
    fRegion = region;
    fOp = op;

    fInfo.push(SkObjectParser::RegionToString(region));
    fInfo.push(SkObjectParser::RegionOpToString(op));
}

void SkClipRegionCommand::execute(SkCanvas* canvas) const {
    canvas->clipRegion(fRegion, fOp);
}

SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkRegion::Op op, bool doAA)
    : INHERITED(CLIP_RECT) {
    fRect = rect;
    fOp = op;
    fDoAA = doAA;

    fInfo.push(SkObjectParser::RectToString(rect));
    fInfo.push(SkObjectParser::RegionOpToString(op));
    fInfo.push(SkObjectParser::BoolToString(doAA));
}

void SkClipRectCommand::execute(SkCanvas* canvas) const {
    canvas->clipRect(fRect, fOp, fDoAA);
}

SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkRegion::Op op, bool doAA)
    : INHERITED(CLIP_RRECT) {
    fRRect = rrect;
    fOp = op;
    fDoAA = doAA;

    fInfo.push(SkObjectParser::RRectToString(rrect));
    fInfo.push(SkObjectParser::RegionOpToString(op));
    fInfo.push(SkObjectParser::BoolToString(doAA));
}

void SkClipRRectCommand::execute(SkCanvas* canvas) const {
    canvas->clipRRect(fRRect, fOp, fDoAA);
}

bool SkClipRRectCommand::render(SkCanvas* canvas) const {
    render_rrect(canvas, fRRect);
    return true;
}

SkConcatCommand::SkConcatCommand(const SkMatrix& matrix)
    : INHERITED(CONCAT) {
    fMatrix = matrix;

    fInfo.push(SkObjectParser::MatrixToString(matrix));
}

void SkConcatCommand::execute(SkCanvas* canvas) const {
    canvas->concat(fMatrix);
}

SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
                                         const SkPaint* paint)
    : INHERITED(DRAW_BITMAP) {
    fBitmap = bitmap;
    fLeft = left;
    fTop = top;
    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    } else {
        fPaintPtr = NULL;
    }

    fInfo.push(SkObjectParser::BitmapToString(bitmap));
    fInfo.push(SkObjectParser::ScalarToString(left, "SkScalar left: "));
    fInfo.push(SkObjectParser::ScalarToString(top, "SkScalar top: "));
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
}

void SkDrawBitmapCommand::execute(SkCanvas* canvas) const {
    canvas->drawBitmap(fBitmap, fLeft, fTop, fPaintPtr);
}

bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
    render_bitmap(canvas, fBitmap);
    return true;
}

SkDrawBitmapMatrixCommand::SkDrawBitmapMatrixCommand(const SkBitmap& bitmap,
                                                     const SkMatrix& matrix,
                                                     const SkPaint* paint)
    : INHERITED(DRAW_BITMAP_MATRIX) {
    fBitmap = bitmap;
    fMatrix = matrix;
    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    } else {
        fPaintPtr = NULL;
    }

    fInfo.push(SkObjectParser::BitmapToString(bitmap));
    fInfo.push(SkObjectParser::MatrixToString(matrix));
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
}

void SkDrawBitmapMatrixCommand::execute(SkCanvas* canvas) const {
    canvas->drawBitmapMatrix(fBitmap, fMatrix, fPaintPtr);
}

bool SkDrawBitmapMatrixCommand::render(SkCanvas* canvas) const {
    render_bitmap(canvas, fBitmap);
    return true;
}

SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
                                                 const SkRect& dst, const SkPaint* paint)
    : INHERITED(DRAW_BITMAP_NINE) {
    fBitmap = bitmap;
    fCenter = center;
    fDst = dst;
    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    } else {
        fPaintPtr = NULL;
    }

    fInfo.push(SkObjectParser::BitmapToString(bitmap));
    fInfo.push(SkObjectParser::IRectToString(center));
    fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
}

void SkDrawBitmapNineCommand::execute(SkCanvas* canvas) const {
    canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaintPtr);
}

bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
    render_bitmap(canvas, fBitmap);
    return true;
}

SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
                                                 const SkRect& dst, const SkPaint* paint,
                                                 SkCanvas::DrawBitmapRectFlags flags)
    : INHERITED(DRAW_BITMAP_RECT_TO_RECT) {
    fBitmap = bitmap;
    if (src) {
        fSrc = *src;
    } else {
        fSrc.setEmpty();
    }
    fDst = dst;

    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    } else {
        fPaintPtr = NULL;
    }
    fFlags = flags;

    fInfo.push(SkObjectParser::BitmapToString(bitmap));
    if (src) {
        fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
    }
    fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
    fInfo.push(SkObjectParser::IntToString(fFlags, "Flags: "));
}

void SkDrawBitmapRectCommand::execute(SkCanvas* canvas) const {
    canvas->drawBitmapRectToRect(fBitmap, this->srcRect(), fDst, fPaintPtr, fFlags);
}

bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
    render_bitmap(canvas, fBitmap, this->srcRect());
    return true;
}

SkDrawDataCommand::SkDrawDataCommand(const void* data, size_t length)
    : INHERITED(DRAW_DATA) {
    fData = new char[length];
    memcpy(fData, data, length);
    fLength = length;

    // TODO: add display of actual data?
    SkString* str = new SkString;
    str->appendf("length: %d", (int) length);
    fInfo.push(str);
}

void SkDrawDataCommand::execute(SkCanvas* canvas) const {
    canvas->drawData(fData, fLength);
}

SkBeginCommentGroupCommand::SkBeginCommentGroupCommand(const char* description)
    : INHERITED(BEGIN_COMMENT_GROUP)
    , fDescription(description) {
    SkString* temp = new SkString;
    temp->appendf("Description: %s", description);
    fInfo.push(temp);
}

SkCommentCommand::SkCommentCommand(const char* kywd, const char* value)
    : INHERITED(COMMENT)
    , fKywd(kywd)
    , fValue(value) {
    SkString* temp = new SkString;
    temp->appendf("%s: %s", kywd, value);
    fInfo.push(temp);
}

SkEndCommentGroupCommand::SkEndCommentGroupCommand()
    : INHERITED(END_COMMENT_GROUP) {
}

SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
    : INHERITED(DRAW_OVAL) {
    fOval = oval;
    fPaint = paint;

    fInfo.push(SkObjectParser::RectToString(oval));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawOvalCommand::execute(SkCanvas* canvas) const {
    canvas->drawOval(fOval, fPaint);
}

bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
    canvas->clear(0xFFFFFFFF);
    canvas->save();

    xlate_and_scale_to_bounds(canvas, fOval);

    SkPaint p;
    p.setColor(SK_ColorBLACK);
    p.setStyle(SkPaint::kStroke_Style);

    canvas->drawOval(fOval, p);
    canvas->restore();

    return true;
}

SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint)
    : INHERITED(DRAW_PAINT) {
    fPaint = paint;

    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawPaintCommand::execute(SkCanvas* canvas) const {
    canvas->drawPaint(fPaint);
}

bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
    canvas->clear(0xFFFFFFFF);
    canvas->drawPaint(fPaint);
    return true;
}

SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint)
    : INHERITED(DRAW_PATH) {
    fPath = path;
    fPaint = paint;

    fInfo.push(SkObjectParser::PathToString(path));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawPathCommand::execute(SkCanvas* canvas) const {
    canvas->drawPath(fPath, fPaint);
}

bool SkDrawPathCommand::render(SkCanvas* canvas) const {
    render_path(canvas, fPath);
    return true;
}

SkDrawPictureCommand::SkDrawPictureCommand(const SkPicture* picture,
                                           const SkMatrix* matrix,
                                           const SkPaint* paint)
    : INHERITED(DRAW_PICTURE)
    , fPicture(SkRef(picture))
    , fMatrixPtr(NULL)
    , fPaintPtr(NULL) {

    if (matrix) {
        fMatrix = *matrix;
        fMatrixPtr = &fMatrix;
    }
    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    }

    SkString* temp = new SkString;
    temp->appendf("SkPicture: L: %f T: %f R: %f B: %f",
                  picture->cullRect().fLeft, picture->cullRect().fTop,
                  picture->cullRect().fRight, picture->cullRect().fBottom);
    fInfo.push(temp);
    if (matrix) {
        fInfo.push(SkObjectParser::MatrixToString(*matrix));
    }
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
}

void SkDrawPictureCommand::execute(SkCanvas* canvas) const {
    canvas->drawPicture(fPicture, fMatrixPtr, fPaintPtr);
}

bool SkDrawPictureCommand::render(SkCanvas* canvas) const {
    canvas->clear(0xFFFFFFFF);
    canvas->save();

    xlate_and_scale_to_bounds(canvas, fPicture->cullRect());

    canvas->drawPicture(fPicture.get());

    canvas->restore();

    return true;
}

SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
                                         const SkPoint pts[], const SkPaint& paint)
    : INHERITED(DRAW_POINTS) {
    fMode = mode;
    fCount = count;
    fPts = new SkPoint[count];
    memcpy(fPts, pts, count * sizeof(SkPoint));
    fPaint = paint;

    fInfo.push(SkObjectParser::PointsToString(pts, count));
    fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
                                              "Points: "));
    fInfo.push(SkObjectParser::PointModeToString(mode));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawPointsCommand::execute(SkCanvas* canvas) const {
    canvas->drawPoints(fMode, fCount, fPts, fPaint);
}

bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
    canvas->clear(0xFFFFFFFF);
    canvas->save();

    SkRect bounds;

    bounds.setEmpty();
    for (unsigned int i = 0; i < fCount; ++i) {
        bounds.growToInclude(fPts[i].fX, fPts[i].fY);
    }

    xlate_and_scale_to_bounds(canvas, bounds);

    SkPaint p;
    p.setColor(SK_ColorBLACK);
    p.setStyle(SkPaint::kStroke_Style);

    canvas->drawPoints(fMode, fCount, fPts, p);
    canvas->restore();

    return true;
}

SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
                                           const SkPoint pos[], const SkPaint& paint)
    : INHERITED(DRAW_POS_TEXT) {
    size_t numPts = paint.countText(text, byteLength);

    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;

    fPos = new SkPoint[numPts];
    memcpy(fPos, pos, numPts * sizeof(SkPoint));

    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    // TODO(chudy): Test that this works.
    fInfo.push(SkObjectParser::PointsToString(pos, 1));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawPosTextCommand::execute(SkCanvas* canvas) const {
    canvas->drawPosText(fText, fByteLength, fPos, fPaint);
}


SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
                                             const SkScalar xpos[], SkScalar constY,
                                             const SkPaint& paint)
    : INHERITED(DRAW_POS_TEXT_H) {
    size_t numPts = paint.countText(text, byteLength);

    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;

    fXpos = new SkScalar[numPts];
    memcpy(fXpos, xpos, numPts * sizeof(SkScalar));

    fConstY = constY;
    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
    fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawPosTextHCommand::execute(SkCanvas* canvas) const {
    canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
}

SkDrawTextBlobCommand::SkDrawTextBlobCommand(const SkTextBlob* blob, SkScalar x, SkScalar y,
                                             const SkPaint& paint)
    : INHERITED(DRAW_TEXT_BLOB)
    , fBlob(blob)
    , fXPos(x)
    , fYPos(y)
    , fPaint(paint) {

    blob->ref();

    // FIXME: push blob info
    fInfo.push(SkObjectParser::ScalarToString(x, "XPOS: "));
    fInfo.push(SkObjectParser::ScalarToString(x, "YPOS: "));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawTextBlobCommand::execute(SkCanvas* canvas) const {
    canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint);
}

bool SkDrawTextBlobCommand::render(SkCanvas* canvas) const {
    canvas->clear(SK_ColorWHITE);
    canvas->save();

    SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos);
    xlate_and_scale_to_bounds(canvas, bounds);

    canvas->drawTextBlob(fBlob.get(), fXPos, fYPos, fPaint);

    canvas->restore();

    return true;
}

SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint)
    : INHERITED(DRAW_RECT) {
    fRect = rect;
    fPaint = paint;

    fInfo.push(SkObjectParser::RectToString(rect));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawRectCommand::execute(SkCanvas* canvas) const {
    canvas->drawRect(fRect, fPaint);
}

SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
    : INHERITED(DRAW_RRECT) {
    fRRect = rrect;
    fPaint = paint;

    fInfo.push(SkObjectParser::RRectToString(rrect));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawRRectCommand::execute(SkCanvas* canvas) const {
    canvas->drawRRect(fRRect, fPaint);
}

bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
    render_rrect(canvas, fRRect);
    return true;
}

SkDrawDRRectCommand::SkDrawDRRectCommand(const SkRRect& outer,
                                         const SkRRect& inner,
                                         const SkPaint& paint)
    : INHERITED(DRAW_DRRECT) {
    fOuter = outer;
    fInner = inner;
    fPaint = paint;

    fInfo.push(SkObjectParser::RRectToString(outer));
    fInfo.push(SkObjectParser::RRectToString(inner));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawDRRectCommand::execute(SkCanvas* canvas) const {
    canvas->drawDRRect(fOuter, fInner, fPaint);
}

bool SkDrawDRRectCommand::render(SkCanvas* canvas) const {
    render_drrect(canvas, fOuter, fInner);
    return true;
}

SkDrawSpriteCommand::SkDrawSpriteCommand(const SkBitmap& bitmap, int left, int top,
                                         const SkPaint* paint)
    : INHERITED(DRAW_SPRITE) {
    fBitmap = bitmap;
    fLeft = left;
    fTop = top;
    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    } else {
        fPaintPtr = NULL;
    }

    fInfo.push(SkObjectParser::BitmapToString(bitmap));
    fInfo.push(SkObjectParser::IntToString(left, "Left: "));
    fInfo.push(SkObjectParser::IntToString(top, "Top: "));
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
}

void SkDrawSpriteCommand::execute(SkCanvas* canvas) const {
    canvas->drawSprite(fBitmap, fLeft, fTop, fPaintPtr);
}

bool SkDrawSpriteCommand::render(SkCanvas* canvas) const {
    render_bitmap(canvas, fBitmap);
    return true;
}

SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                                     const SkPaint& paint)
    : INHERITED(DRAW_TEXT) {
    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;
    fX = x;
    fY = y;
    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
    fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawTextCommand::execute(SkCanvas* canvas) const {
    canvas->drawText(fText, fByteLength, fX, fY, fPaint);
}

SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
                                                 const SkPath& path, const SkMatrix* matrix,
                                                 const SkPaint& paint)
    : INHERITED(DRAW_TEXT_ON_PATH) {
    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;
    fPath = path;
    if (matrix) {
        fMatrix = *matrix;
    } else {
        fMatrix.setIdentity();
    }
    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    fInfo.push(SkObjectParser::PathToString(path));
    if (matrix) {
        fInfo.push(SkObjectParser::MatrixToString(*matrix));
    }
    fInfo.push(SkObjectParser::PaintToString(paint));
}

void SkDrawTextOnPathCommand::execute(SkCanvas* canvas) const {
    canvas->drawTextOnPath(fText, fByteLength, fPath,
                           fMatrix.isIdentity() ? NULL : &fMatrix,
                           fPaint);
}

SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int vertexCount,
                                             const SkPoint vertices[], const SkPoint texs[],
                                             const SkColor colors[], SkXfermode* xfermode,
                                             const uint16_t indices[], int indexCount,
                                             const SkPaint& paint)
    : INHERITED(DRAW_VERTICES) {
    fVmode = vmode;

    fVertexCount = vertexCount;

    fVertices = new SkPoint[vertexCount];
    memcpy(fVertices, vertices, vertexCount * sizeof(SkPoint));

    if (texs) {
        fTexs = new SkPoint[vertexCount];
        memcpy(fTexs, texs, vertexCount * sizeof(SkPoint));
    } else {
        fTexs = NULL;
    }

    if (colors) {
        fColors = new SkColor[vertexCount];
        memcpy(fColors, colors, vertexCount * sizeof(SkColor));
    } else {
        fColors = NULL;
    }

    fXfermode = xfermode;
    if (fXfermode) {
        fXfermode->ref();
    }

    if (indexCount > 0) {
        fIndices = new uint16_t[indexCount];
        memcpy(fIndices, indices, indexCount * sizeof(uint16_t));
    } else {
        fIndices = NULL;
    }

    fIndexCount = indexCount;
    fPaint = paint;

    // TODO(chudy)
    fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
    fInfo.push(SkObjectParser::PaintToString(paint));
}

SkDrawVerticesCommand::~SkDrawVerticesCommand() {
    delete [] fVertices;
    delete [] fTexs;
    delete [] fColors;
    SkSafeUnref(fXfermode);
    delete [] fIndices;
}

void SkDrawVerticesCommand::execute(SkCanvas* canvas) const {
    canvas->drawVertices(fVmode, fVertexCount, fVertices,
                         fTexs, fColors, fXfermode, fIndices,
                         fIndexCount, fPaint);
}

SkRestoreCommand::SkRestoreCommand()
    : INHERITED(RESTORE) {
    fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
}

void SkRestoreCommand::execute(SkCanvas* canvas) const {
    canvas->restore();
}

void SkRestoreCommand::trackSaveState(int* state) {
    (*state)--;
}

SkRotateCommand::SkRotateCommand(SkScalar degrees)
    : INHERITED(ROTATE) {
    fDegrees = degrees;

    fInfo.push(SkObjectParser::ScalarToString(degrees, "SkScalar degrees: "));
}

void SkRotateCommand::execute(SkCanvas* canvas) const {
    canvas->rotate(fDegrees);
}

SkSaveCommand::SkSaveCommand()
    : INHERITED(SAVE) {
}

void SkSaveCommand::execute(SkCanvas* canvas) const {
    canvas->save();
}

void SkSaveCommand::trackSaveState(int* state) {
    (*state)++;
}

SkSaveLayerCommand::SkSaveLayerCommand(const SkRect* bounds, const SkPaint* paint,
                                       SkCanvas::SaveFlags flags)
    : INHERITED(SAVE_LAYER) {
    if (bounds) {
        fBounds = *bounds;
    } else {
        fBounds.setEmpty();
    }

    if (paint) {
        fPaint = *paint;
        fPaintPtr = &fPaint;
    } else {
        fPaintPtr = NULL;
    }
    fFlags = flags;

    if (bounds) {
        fInfo.push(SkObjectParser::RectToString(*bounds, "Bounds: "));
    }
    if (paint) {
        fInfo.push(SkObjectParser::PaintToString(*paint));
    }
    fInfo.push(SkObjectParser::SaveFlagsToString(flags));
}

void SkSaveLayerCommand::execute(SkCanvas* canvas) const {
    canvas->saveLayer(fBounds.isEmpty() ? NULL : &fBounds,
                      fPaintPtr,
                      fFlags);
}

void SkSaveLayerCommand::vizExecute(SkCanvas* canvas) const {
    canvas->save();
}

void SkSaveLayerCommand::trackSaveState(int* state) {
    (*state)++;
}

SkScaleCommand::SkScaleCommand(SkScalar sx, SkScalar sy)
    : INHERITED(SCALE) {
    fSx = sx;
    fSy = sy;

    fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
    fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
}

void SkScaleCommand::execute(SkCanvas* canvas) const {
    canvas->scale(fSx, fSy);
}

SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix)
    : INHERITED(SET_MATRIX) {
    fUserMatrix.reset();
    fMatrix = matrix;

    fInfo.push(SkObjectParser::MatrixToString(matrix));
}

void SkSetMatrixCommand::setUserMatrix(const SkMatrix& userMatrix) {
    fUserMatrix = userMatrix;
}

void SkSetMatrixCommand::execute(SkCanvas* canvas) const {
    SkMatrix temp = SkMatrix::Concat(fUserMatrix, fMatrix);
    canvas->setMatrix(temp);
}

SkSkewCommand::SkSkewCommand(SkScalar sx, SkScalar sy)
    : INHERITED(SKEW) {
    fSx = sx;
    fSy = sy;

    fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
    fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
}

void SkSkewCommand::execute(SkCanvas* canvas) const {
    canvas->skew(fSx, fSy);
}

SkTranslateCommand::SkTranslateCommand(SkScalar dx, SkScalar dy)
    : INHERITED(TRANSLATE) {
    fDx = dx;
    fDy = dy;

    fInfo.push(SkObjectParser::ScalarToString(dx, "SkScalar dx: "));
    fInfo.push(SkObjectParser::ScalarToString(dy, "SkScalar dy: "));
}

void SkTranslateCommand::execute(SkCanvas* canvas) const {
    canvas->translate(fDx, fDy);
}

SkPushCullCommand::SkPushCullCommand(const SkRect& cullRect)
    : INHERITED(PUSH_CULL)
    , fCullRect(cullRect) {
    fInfo.push(SkObjectParser::RectToString(cullRect));
}

void SkPushCullCommand::execute(SkCanvas* canvas) const {
    canvas->pushCull(fCullRect);
}

void SkPushCullCommand::vizExecute(SkCanvas* canvas) const {
    canvas->pushCull(fCullRect);

    SkPaint p;
    p.setColor(SK_ColorCYAN);
    p.setStyle(SkPaint::kStroke_Style);
    canvas->drawRect(fCullRect, p);
}

SkPopCullCommand::SkPopCullCommand() : INHERITED(POP_CULL) { }

void SkPopCullCommand::execute(SkCanvas* canvas) const {
    canvas->popCull();
}
