/*
    This file is part of the WebKit open source project.
    This file has been generated by generate-bindings.pl. DO NOT MODIFY!

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "config.h"

#if ENABLE(SVG) && ENABLE(FILTERS)

#include "JSSVGFEGaussianBlurElement.h"

#include "CSSMutableStyleDeclaration.h"
#include "CSSStyleDeclaration.h"
#include "CSSValue.h"
#include "JSCSSStyleDeclaration.h"
#include "JSCSSValue.h"
#include "JSSVGAnimatedLength.h"
#include "JSSVGAnimatedNumber.h"
#include "JSSVGAnimatedString.h"
#include "SVGFEGaussianBlurElement.h"
#include <runtime/Error.h>
#include <wtf/GetPtr.h>

using namespace JSC;

namespace WebCore {

ASSERT_CLASS_FITS_IN_CELL(JSSVGFEGaussianBlurElement);

/* Hash table */

static const HashTableValue JSSVGFEGaussianBlurElementTableValues[12] =
{
    { "in1", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementIn1), (intptr_t)0 },
    { "stdDeviationX", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementStdDeviationX), (intptr_t)0 },
    { "stdDeviationY", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementStdDeviationY), (intptr_t)0 },
    { "x", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementX), (intptr_t)0 },
    { "y", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementY), (intptr_t)0 },
    { "width", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementWidth), (intptr_t)0 },
    { "height", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementHeight), (intptr_t)0 },
    { "result", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementResult), (intptr_t)0 },
    { "className", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementClassName), (intptr_t)0 },
    { "style", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementStyle), (intptr_t)0 },
    { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsSVGFEGaussianBlurElementConstructor), (intptr_t)0 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSSVGFEGaussianBlurElementTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 255, JSSVGFEGaussianBlurElementTableValues, 0 };
#else
    { 34, 31, JSSVGFEGaussianBlurElementTableValues, 0 };
#endif

/* Hash table for constructor */

static const HashTableValue JSSVGFEGaussianBlurElementConstructorTableValues[1] =
{
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSSVGFEGaussianBlurElementConstructorTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 0, JSSVGFEGaussianBlurElementConstructorTableValues, 0 };
#else
    { 1, 0, JSSVGFEGaussianBlurElementConstructorTableValues, 0 };
#endif

class JSSVGFEGaussianBlurElementConstructor : public DOMConstructorObject {
public:
    JSSVGFEGaussianBlurElementConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
        : DOMConstructorObject(JSSVGFEGaussianBlurElementConstructor::createStructure(globalObject->objectPrototype()), globalObject)
    {
        putDirect(exec->propertyNames().prototype, JSSVGFEGaussianBlurElementPrototype::self(exec, globalObject), None);
    }
    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    virtual const ClassInfo* classInfo() const { return &s_info; }
    static const ClassInfo s_info;

    static PassRefPtr<Structure> createStructure(JSValue proto) 
    { 
        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
    }
    
protected:
    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags;
};

const ClassInfo JSSVGFEGaussianBlurElementConstructor::s_info = { "SVGFEGaussianBlurElementConstructor", 0, &JSSVGFEGaussianBlurElementConstructorTable, 0 };

bool JSSVGFEGaussianBlurElementConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSSVGFEGaussianBlurElementConstructor, DOMObject>(exec, &JSSVGFEGaussianBlurElementConstructorTable, this, propertyName, slot);
}

bool JSSVGFEGaussianBlurElementConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSSVGFEGaussianBlurElementConstructor, DOMObject>(exec, &JSSVGFEGaussianBlurElementConstructorTable, this, propertyName, descriptor);
}

/* Hash table for prototype */

static const HashTableValue JSSVGFEGaussianBlurElementPrototypeTableValues[3] =
{
    { "setStdDeviation", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsSVGFEGaussianBlurElementPrototypeFunctionSetStdDeviation), (intptr_t)2 },
    { "getPresentationAttribute", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsSVGFEGaussianBlurElementPrototypeFunctionGetPresentationAttribute), (intptr_t)1 },
    { 0, 0, 0, 0 }
};

static JSC_CONST_HASHTABLE HashTable JSSVGFEGaussianBlurElementPrototypeTable =
#if ENABLE(PERFECT_HASH_SIZE)
    { 1, JSSVGFEGaussianBlurElementPrototypeTableValues, 0 };
#else
    { 4, 3, JSSVGFEGaussianBlurElementPrototypeTableValues, 0 };
#endif

const ClassInfo JSSVGFEGaussianBlurElementPrototype::s_info = { "SVGFEGaussianBlurElementPrototype", 0, &JSSVGFEGaussianBlurElementPrototypeTable, 0 };

JSObject* JSSVGFEGaussianBlurElementPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMPrototype<JSSVGFEGaussianBlurElement>(exec, globalObject);
}

bool JSSVGFEGaussianBlurElementPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticFunctionSlot<JSObject>(exec, &JSSVGFEGaussianBlurElementPrototypeTable, this, propertyName, slot);
}

bool JSSVGFEGaussianBlurElementPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticFunctionDescriptor<JSObject>(exec, &JSSVGFEGaussianBlurElementPrototypeTable, this, propertyName, descriptor);
}

const ClassInfo JSSVGFEGaussianBlurElement::s_info = { "SVGFEGaussianBlurElement", &JSSVGElement::s_info, &JSSVGFEGaussianBlurElementTable, 0 };

JSSVGFEGaussianBlurElement::JSSVGFEGaussianBlurElement(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<SVGFEGaussianBlurElement> impl)
    : JSSVGElement(structure, globalObject, impl)
{
}

JSObject* JSSVGFEGaussianBlurElement::createPrototype(ExecState* exec, JSGlobalObject* globalObject)
{
    return new (exec) JSSVGFEGaussianBlurElementPrototype(JSSVGFEGaussianBlurElementPrototype::createStructure(JSSVGElementPrototype::self(exec, globalObject)));
}

bool JSSVGFEGaussianBlurElement::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
    return getStaticValueSlot<JSSVGFEGaussianBlurElement, Base>(exec, &JSSVGFEGaussianBlurElementTable, this, propertyName, slot);
}

bool JSSVGFEGaussianBlurElement::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    return getStaticValueDescriptor<JSSVGFEGaussianBlurElement, Base>(exec, &JSSVGFEGaussianBlurElementTable, this, propertyName, descriptor);
}

JSValue jsSVGFEGaussianBlurElementIn1(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedString> obj = imp->in1Animated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementStdDeviationX(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedNumber> obj = imp->stdDeviationXAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementStdDeviationY(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedNumber> obj = imp->stdDeviationYAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementX(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedLength> obj = imp->xAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementY(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedLength> obj = imp->yAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementWidth(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedLength> obj = imp->widthAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementHeight(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedLength> obj = imp->heightAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementResult(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedString> obj = imp->resultAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementClassName(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    RefPtr<SVGAnimatedString> obj = imp->classNameAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);
    return result;
}

JSValue jsSVGFEGaussianBlurElementStyle(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* castedThis = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThis->impl());
    JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->style()));
    return result;
}

JSValue jsSVGFEGaussianBlurElementConstructor(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFEGaussianBlurElement* domObject = static_cast<JSSVGFEGaussianBlurElement*>(asObject(slotBase));
    return JSSVGFEGaussianBlurElement::getConstructor(exec, domObject->globalObject());
}
JSValue JSSVGFEGaussianBlurElement::getConstructor(ExecState* exec, JSGlobalObject* globalObject)
{
    return getDOMConstructor<JSSVGFEGaussianBlurElementConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));
}

JSValue JSC_HOST_CALL jsSVGFEGaussianBlurElementPrototypeFunctionSetStdDeviation(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSSVGFEGaussianBlurElement::s_info))
        return throwError(exec, TypeError);
    JSSVGFEGaussianBlurElement* castedThisObj = static_cast<JSSVGFEGaussianBlurElement*>(asObject(thisValue));
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThisObj->impl());
    float stdDeviationX = args.at(0).toFloat(exec);
    float stdDeviationY = args.at(1).toFloat(exec);

    imp->setStdDeviation(stdDeviationX, stdDeviationY);
    return jsUndefined();
}

JSValue JSC_HOST_CALL jsSVGFEGaussianBlurElementPrototypeFunctionGetPresentationAttribute(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.inherits(&JSSVGFEGaussianBlurElement::s_info))
        return throwError(exec, TypeError);
    JSSVGFEGaussianBlurElement* castedThisObj = static_cast<JSSVGFEGaussianBlurElement*>(asObject(thisValue));
    SVGFEGaussianBlurElement* imp = static_cast<SVGFEGaussianBlurElement*>(castedThisObj->impl());
    const UString& name = args.at(0).toString(exec);


    JSC::JSValue result = toJS(exec, castedThisObj->globalObject(), WTF::getPtr(imp->getPresentationAttribute(name)));
    return result;
}


}

#endif // ENABLE(SVG) && ENABLE(FILTERS)
