v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.CanvasRenderingContext2D.drawImage()");
    CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder());

    v8::Handle<v8::Value> arg = args[0];

    if (V8HTMLImageElement::HasInstance(arg)) {
        ExceptionCode ec = 0;
        HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg));
        switch (args.Length()) {
        case 3:
            context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2]));
            break;
        case 5:
            context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec);
            if (ec != 0) {
                V8Proxy::setDOMException(ec);
                return notHandledByInterceptor();
            }
            break;
        case 9:
            context->drawImage(imageElement, 
                FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), 
                FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])),
                ec);
            if (ec != 0) {
                V8Proxy::setDOMException(ec);
                return notHandledByInterceptor();
            }
            break;
        default:
            return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError);
        }
        return v8::Undefined();
    }

    // HTMLCanvasElement
    if (V8HTMLCanvasElement::HasInstance(arg)) {
        ExceptionCode ec = 0;
        HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg));
        switch (args.Length()) {
        case 3:
            context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2]));
            break;
        case 5:
            context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec);
            if (ec != 0) {
                V8Proxy::setDOMException(ec);
                return notHandledByInterceptor();
            }
            break;
        case 9:
            context->drawImage(canvasElement,
                FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])),
                FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])),
                ec);
            if (ec != 0) {
                V8Proxy::setDOMException(ec);
                return notHandledByInterceptor();
            }
            break;
        default:
            return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError);
        }
        return v8::Undefined();
    }

#if ENABLE(VIDEO)
    // HTMLVideoElement
    if (V8HTMLVideoElement::HasInstance(arg)) {
        ExceptionCode ec = 0;
        HTMLVideoElement* videoElement = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg));
        switch (args.Length()) {
        case 3:
            context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2]));
            break;
        case 5:
            context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec);
            if (ec != 0) {
                V8Proxy::setDOMException(ec);
                return notHandledByInterceptor();
            }
            break;
        case 9:
            context->drawImage(videoElement,
                FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])),
                FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])),
                ec);
            if (ec != 0) {
                V8Proxy::setDOMException(ec);
                return notHandledByInterceptor();
            }
            break;
        default:
            return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError);
        }
        return v8::Undefined();
    }
#endif

    V8Proxy::setDOMException(TYPE_MISMATCH_ERR);
    return notHandledByInterceptor();
}
JSValue* JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& args)
{ 
    CanvasRenderingContext2D* context = impl();

    // DrawImage has three variants:
    //     drawImage(img, dx, dy)
    //     drawImage(img, dx, dy, dw, dh)
    //     drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)
    // Composite operation is specified with globalCompositeOperation.
    // The img parameter can be a <img> or <canvas> element.
    JSValue* value = args[0];
    if (!value->isObject())
        return throwError(exec, TypeError);
    JSObject* o = static_cast<JSObject*>(value);
    
    ExceptionCode ec = 0;
    if (o->inherits(&JSHTMLImageElement::s_info)) {
        HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
        switch (args.size()) {
            case 3:
                context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec));
                break;
            case 5:
                context->drawImage(imgElt, args[1]->toFloat(exec), args[2]->toFloat(exec),
                                   args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
                setDOMException(exec, ec);
                break;
            case 9:
                context->drawImage(imgElt, FloatRect(args[1]->toFloat(exec), args[2]->toFloat(exec),
                                   args[3]->toFloat(exec), args[4]->toFloat(exec)),
                                   FloatRect(args[5]->toFloat(exec), args[6]->toFloat(exec),
                                   args[7]->toFloat(exec), args[8]->toFloat(exec)), ec);
                setDOMException(exec, ec);
                break;
            default:
                return throwError(exec, SyntaxError);
        }
    } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
        HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(args[0])->impl());
        switch (args.size()) {
            case 3:
                context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec));
                break;
            case 5:
                context->drawImage(canvas, args[1]->toFloat(exec), args[2]->toFloat(exec),
                                   args[3]->toFloat(exec), args[4]->toFloat(exec), ec);
                setDOMException(exec, ec);
                break;
            case 9:
                context->drawImage(canvas, FloatRect(args[1]->toFloat(exec), args[2]->toFloat(exec),
                                   args[3]->toFloat(exec), args[4]->toFloat(exec)),
                                   FloatRect(args[5]->toFloat(exec), args[6]->toFloat(exec),
                                   args[7]->toFloat(exec), args[8]->toFloat(exec)), ec);
                setDOMException(exec, ec);
                break;
            default:
                return throwError(exec, SyntaxError);
        }
    } else {
        setDOMException(exec, TYPE_MISMATCH_ERR);
        return 0;
    }
    
    return jsUndefined();    
}
JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& args)
{ 
    CanvasRenderingContext2D* context = impl();

    // DrawImage has three variants:
    //     drawImage(img, dx, dy)
    //     drawImage(img, dx, dy, dw, dh)
    //     drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)
    // Composite operation is specified with globalCompositeOperation.
    // The img parameter can be a <img> or <canvas> element.
    JSValue value = args.at(0);
    if (!value.isObject())
        return throwError(exec, TypeError);
    JSObject* o = asObject(value);
    
    ExceptionCode ec = 0;
    if (o->inherits(&JSHTMLImageElement::s_info)) {
        HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl());
        switch (args.size()) {
            case 3:
                context->drawImage(imgElt, args.at(1).toFloat(exec), args.at(2).toFloat(exec));
                break;
            case 5:
                context->drawImage(imgElt, args.at(1).toFloat(exec), args.at(2).toFloat(exec),
                                   args.at(3).toFloat(exec), args.at(4).toFloat(exec), ec);
                setDOMException(exec, ec);
                break;
            case 9:
                context->drawImage(imgElt, FloatRect(args.at(1).toFloat(exec), args.at(2).toFloat(exec),
                                   args.at(3).toFloat(exec), args.at(4).toFloat(exec)),
                                   FloatRect(args.at(5).toFloat(exec), args.at(6).toFloat(exec),
                                   args.at(7).toFloat(exec), args.at(8).toFloat(exec)), ec);
                setDOMException(exec, ec);
                break;
            default:
                return throwError(exec, SyntaxError);
        }
    } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
        HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl());
        switch (args.size()) {
            case 3:
                context->drawImage(canvas, args.at(1).toFloat(exec), args.at(2).toFloat(exec));
                break;
            case 5:
                context->drawImage(canvas, args.at(1).toFloat(exec), args.at(2).toFloat(exec),
                                   args.at(3).toFloat(exec), args.at(4).toFloat(exec), ec);
                setDOMException(exec, ec);
                break;
            case 9:
                context->drawImage(canvas, FloatRect(args.at(1).toFloat(exec), args.at(2).toFloat(exec),
                                   args.at(3).toFloat(exec), args.at(4).toFloat(exec)),
                                   FloatRect(args.at(5).toFloat(exec), args.at(6).toFloat(exec),
                                   args.at(7).toFloat(exec), args.at(8).toFloat(exec)), ec);
                setDOMException(exec, ec);
                break;
            default:
                return throwError(exec, SyntaxError);
        }
#if ENABLE(VIDEO)
    } else if (o->inherits(&JSHTMLVideoElement::s_info)) {
            HTMLVideoElement* video = static_cast<HTMLVideoElement*>(static_cast<JSHTMLElement*>(o)->impl());
            switch (args.size()) {
                case 3:
                    context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec));
                    break;
                case 5:
                    context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec),
                                       args.at(3).toFloat(exec), args.at(4).toFloat(exec), ec);
                    setDOMException(exec, ec);
                    break;
                case 9:
                    context->drawImage(video, FloatRect(args.at(1).toFloat(exec), args.at(2).toFloat(exec),
                                       args.at(3).toFloat(exec), args.at(4).toFloat(exec)),
                                       FloatRect(args.at(5).toFloat(exec), args.at(6).toFloat(exec),
                                       args.at(7).toFloat(exec), args.at(8).toFloat(exec)), ec);
                    setDOMException(exec, ec);
                    break;
                default:
                    return throwError(exec, SyntaxError);
        }
#endif
    } else {
        setDOMException(exec, TYPE_MISMATCH_ERR);
    }
    
    return jsUndefined();    
}