examples/script/context2d/environment.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the examples of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "environment.h"
       
    43 #include "qcontext2dcanvas.h"
       
    44 #include "context2d.h"
       
    45 #include <QScriptValueIterator>
       
    46 #include <QDateTime>
       
    47 
       
    48 struct FakeDomEvent
       
    49 {
       
    50     enum KeyCodes  {
       
    51         DOM_VK_UNDEFINED            = 0x0,
       
    52         DOM_VK_RIGHT_ALT            = 0x12,
       
    53         DOM_VK_LEFT_ALT             = 0x12,
       
    54         DOM_VK_LEFT_CONTROL         = 0x11,
       
    55         DOM_VK_RIGHT_CONTROL        = 0x11,
       
    56         DOM_VK_LEFT_SHIFT           = 0x10,
       
    57         DOM_VK_RIGHT_SHIFT          = 0x10,
       
    58         DOM_VK_META                 = 0x9D,
       
    59         DOM_VK_BACK_SPACE           = 0x08,
       
    60         DOM_VK_CAPS_LOCK            = 0x14,
       
    61         DOM_VK_DELETE               = 0x7F,
       
    62         DOM_VK_END                  = 0x23,
       
    63         DOM_VK_ENTER                = 0x0D,
       
    64         DOM_VK_ESCAPE               = 0x1B,
       
    65         DOM_VK_HOME                 = 0x24,
       
    66         DOM_VK_NUM_LOCK             = 0x90,
       
    67         DOM_VK_PAUSE                = 0x13,
       
    68         DOM_VK_PRINTSCREEN          = 0x9A,
       
    69         DOM_VK_SCROLL_LOCK          = 0x91,
       
    70         DOM_VK_SPACE                = 0x20,
       
    71         DOM_VK_TAB                  = 0x09,
       
    72         DOM_VK_LEFT                 = 0x25,
       
    73         DOM_VK_RIGHT                = 0x27,
       
    74         DOM_VK_UP                   = 0x26,
       
    75         DOM_VK_DOWN                 = 0x28,
       
    76         DOM_VK_PAGE_DOWN            = 0x22,
       
    77         DOM_VK_PAGE_UP              = 0x21,
       
    78         DOM_VK_F1                   = 0x70,
       
    79         DOM_VK_F2                   = 0x71,
       
    80         DOM_VK_F3                   = 0x72,
       
    81         DOM_VK_F4                   = 0x73,
       
    82         DOM_VK_F5                   = 0x74,
       
    83         DOM_VK_F6                   = 0x75,
       
    84         DOM_VK_F7                   = 0x76,
       
    85         DOM_VK_F8                   = 0x77,
       
    86         DOM_VK_F9                   = 0x78,
       
    87         DOM_VK_F10                  = 0x79,
       
    88         DOM_VK_F11                  = 0x7A,
       
    89         DOM_VK_F12                  = 0x7B,
       
    90         DOM_VK_F13                  = 0xF000,
       
    91         DOM_VK_F14                  = 0xF001,
       
    92         DOM_VK_F15                  = 0xF002,
       
    93         DOM_VK_F16                  = 0xF003,
       
    94         DOM_VK_F17                  = 0xF004,
       
    95         DOM_VK_F18                  = 0xF005,
       
    96         DOM_VK_F19                  = 0xF006,
       
    97         DOM_VK_F20                  = 0xF007,
       
    98         DOM_VK_F21                  = 0xF008,
       
    99         DOM_VK_F22                  = 0xF009,
       
   100         DOM_VK_F23                  = 0xF00A,
       
   101         DOM_VK_F24                  = 0xF00B
       
   102     };
       
   103 
       
   104     static int qtToDomKey(int keyCode);
       
   105 };
       
   106 
       
   107 int FakeDomEvent::qtToDomKey(int keyCode)
       
   108 {
       
   109     switch (keyCode) {
       
   110     case Qt::Key_Backspace:
       
   111         return  DOM_VK_BACK_SPACE;
       
   112     case Qt::Key_Enter:
       
   113         return  DOM_VK_ENTER;
       
   114     case Qt::Key_Return:
       
   115         return  DOM_VK_ENTER;
       
   116     case Qt::Key_NumLock:
       
   117         return  DOM_VK_NUM_LOCK;
       
   118     case Qt::Key_Alt:
       
   119         return  DOM_VK_RIGHT_ALT;
       
   120     case Qt::Key_Control:
       
   121         return  DOM_VK_LEFT_CONTROL;
       
   122     case Qt::Key_Shift:
       
   123         return  DOM_VK_LEFT_SHIFT;
       
   124     case Qt::Key_Meta:
       
   125         return  DOM_VK_META;
       
   126     case Qt::Key_CapsLock:
       
   127         return  DOM_VK_CAPS_LOCK;
       
   128     case Qt::Key_Delete:
       
   129         return  DOM_VK_DELETE;
       
   130     case Qt::Key_End:
       
   131         return  DOM_VK_END;
       
   132     case Qt::Key_Escape:
       
   133         return  DOM_VK_ESCAPE;
       
   134     case Qt::Key_Home:
       
   135         return  DOM_VK_HOME;
       
   136     case Qt::Key_Pause:
       
   137         return  DOM_VK_PAUSE;
       
   138     case Qt::Key_Print:
       
   139         return  DOM_VK_PRINTSCREEN;
       
   140     case Qt::Key_ScrollLock:
       
   141         return  DOM_VK_SCROLL_LOCK;
       
   142     case Qt::Key_Left:
       
   143         return  DOM_VK_LEFT;
       
   144     case Qt::Key_Right:
       
   145         return  DOM_VK_RIGHT;
       
   146     case Qt::Key_Up:
       
   147         return  DOM_VK_UP;
       
   148     case Qt::Key_Down:
       
   149         return  DOM_VK_DOWN;
       
   150     case Qt::Key_PageDown:
       
   151         return  DOM_VK_PAGE_DOWN;
       
   152     case Qt::Key_PageUp:
       
   153         return  DOM_VK_PAGE_UP;
       
   154     case Qt::Key_F1:
       
   155         return  DOM_VK_F1;
       
   156     case Qt::Key_F2:
       
   157         return  DOM_VK_F2;
       
   158     case Qt::Key_F3:
       
   159         return  DOM_VK_F3;
       
   160     case Qt::Key_F4:
       
   161         return  DOM_VK_F4;
       
   162     case Qt::Key_F5:
       
   163         return  DOM_VK_F5;
       
   164     case Qt::Key_F6:
       
   165         return  DOM_VK_F6;
       
   166     case Qt::Key_F7:
       
   167         return  DOM_VK_F7;
       
   168     case Qt::Key_F8:
       
   169         return  DOM_VK_F8;
       
   170     case Qt::Key_F9:
       
   171         return  DOM_VK_F9;
       
   172     case Qt::Key_F10:
       
   173         return  DOM_VK_F10;
       
   174     case Qt::Key_F11:
       
   175         return  DOM_VK_F11;
       
   176     case Qt::Key_F12:
       
   177         return  DOM_VK_F12;
       
   178     case Qt::Key_F13:
       
   179         return  DOM_VK_F13;
       
   180     case Qt::Key_F14:
       
   181         return  DOM_VK_F14;
       
   182     case Qt::Key_F15:
       
   183         return  DOM_VK_F15;
       
   184     case Qt::Key_F16:
       
   185         return  DOM_VK_F16;
       
   186     case Qt::Key_F17:
       
   187         return  DOM_VK_F17;
       
   188     case Qt::Key_F18:
       
   189         return  DOM_VK_F18;
       
   190     case Qt::Key_F19:
       
   191         return  DOM_VK_F19;
       
   192     case Qt::Key_F20:
       
   193         return  DOM_VK_F20;
       
   194     case Qt::Key_F21:
       
   195         return  DOM_VK_F21;
       
   196     case Qt::Key_F22:
       
   197         return  DOM_VK_F22;
       
   198     case Qt::Key_F23:
       
   199         return  DOM_VK_F23;
       
   200     case Qt::Key_F24:
       
   201         return  DOM_VK_F24;
       
   202     }
       
   203     return keyCode;
       
   204 }
       
   205 
       
   206 //! [0]
       
   207 Environment::Environment(QObject *parent)
       
   208     : QObject(parent)
       
   209 {
       
   210     m_engine = new QScriptEngine(this);
       
   211 
       
   212     m_document = m_engine->newQObject(
       
   213         new Document(this), QScriptEngine::QtOwnership,
       
   214         QScriptEngine::ExcludeSuperClassContents);
       
   215 
       
   216     CanvasGradientPrototype::setup(m_engine);
       
   217 
       
   218     m_originalGlobalObject = m_engine->globalObject();
       
   219     reset();
       
   220 }
       
   221 //! [0]
       
   222 
       
   223 Environment::~Environment()
       
   224 {
       
   225 }
       
   226 
       
   227 QScriptEngine *Environment::engine() const
       
   228 {
       
   229     return m_engine;
       
   230 }
       
   231 
       
   232 QScriptValue Environment::document() const
       
   233 {
       
   234     return m_document;
       
   235 }
       
   236 
       
   237 int Environment::setTimeout(const QScriptValue &expression, int delay)
       
   238 {
       
   239     if (expression.isString() || expression.isFunction()) {
       
   240         int timerId = startTimer(delay);
       
   241         m_timeoutHash.insert(timerId, expression);
       
   242         return timerId;
       
   243     }
       
   244     return -1;
       
   245 }
       
   246 
       
   247 void Environment::clearTimeout(int timerId)
       
   248 {
       
   249     killTimer(timerId);
       
   250     m_timeoutHash.remove(timerId);
       
   251 }
       
   252 
       
   253 //! [1]
       
   254 int Environment::setInterval(const QScriptValue &expression, int delay)
       
   255 {
       
   256     if (expression.isString() || expression.isFunction()) {
       
   257         int timerId = startTimer(delay);
       
   258         m_intervalHash.insert(timerId, expression);
       
   259         return timerId;
       
   260     }
       
   261     return -1;
       
   262 }
       
   263 
       
   264 void Environment::clearInterval(int timerId)
       
   265 {
       
   266     killTimer(timerId);
       
   267     m_intervalHash.remove(timerId);
       
   268 }
       
   269 
       
   270 void Environment::timerEvent(QTimerEvent *event)
       
   271 {
       
   272     int id = event->timerId();
       
   273     QScriptValue expression = m_intervalHash.value(id);
       
   274     if (!expression.isValid()) {
       
   275         expression = m_timeoutHash.value(id);
       
   276         if (expression.isValid())
       
   277             killTimer(id);
       
   278     }
       
   279     if (expression.isString()) {
       
   280         evaluate(expression.toString());
       
   281     } else if (expression.isFunction()) {
       
   282         expression.call();
       
   283     }
       
   284     maybeEmitScriptError();
       
   285 }
       
   286 //! [1]
       
   287 
       
   288 //! [5]
       
   289 void Environment::addCanvas(QContext2DCanvas *canvas)
       
   290 {
       
   291     m_canvases.append(canvas);
       
   292 }
       
   293 
       
   294 QContext2DCanvas *Environment::canvasByName(const QString &name) const
       
   295 {
       
   296     for (int i = 0; i < m_canvases.size(); ++i) {
       
   297         QContext2DCanvas *canvas = m_canvases.at(i);
       
   298         if (canvas->objectName() == name)
       
   299             return canvas;
       
   300     }
       
   301     return 0;
       
   302 }
       
   303 //! [5]
       
   304 
       
   305 QList<QContext2DCanvas*> Environment::canvases() const
       
   306 {
       
   307     return m_canvases;
       
   308 }
       
   309 
       
   310 void Environment::reset()
       
   311 {
       
   312     if (m_engine->isEvaluating())
       
   313         m_engine->abortEvaluation();
       
   314 
       
   315     {
       
   316         QHash<int, QScriptValue>::const_iterator it;
       
   317         for (it = m_intervalHash.constBegin(); it != m_intervalHash.constEnd(); ++it)
       
   318             killTimer(it.key());
       
   319         m_intervalHash.clear();
       
   320         for (it = m_timeoutHash.constBegin(); it != m_timeoutHash.constEnd(); ++it)
       
   321             killTimer(it.key());
       
   322         m_timeoutHash.clear();
       
   323     }
       
   324 
       
   325     for (int i = 0; i < m_canvases.size(); ++i)
       
   326         m_canvases.at(i)->reset();
       
   327 
       
   328     QScriptValue self = m_engine->newQObject(
       
   329         this, QScriptEngine::QtOwnership,
       
   330         QScriptEngine::ExcludeSuperClassContents);
       
   331 
       
   332     {
       
   333         QScriptValueIterator it(m_originalGlobalObject);
       
   334         while (it.hasNext()) {
       
   335             it.next();
       
   336             self.setProperty(it.scriptName(), it.value(), it.flags());
       
   337         }
       
   338     }
       
   339 
       
   340     self.setProperty("self", self);
       
   341     self.setProperty("window", self);
       
   342 
       
   343     QScriptValue navigator = m_engine->newObject();
       
   344     navigator.setProperty("appCodeName", "context2d");
       
   345     navigator.setProperty("appMinorVersion", 1);
       
   346     navigator.setProperty("appVersion", 1);
       
   347     navigator.setProperty("browserLanguage", "en_US");
       
   348     navigator.setProperty("cookieEnabled", false);
       
   349     navigator.setProperty("cpuClass", "i686");
       
   350     navigator.setProperty("onLine", false);
       
   351     navigator.setProperty("platform", "bogus OS");
       
   352     navigator.setProperty("systemLanguage", "en_US");
       
   353     navigator.setProperty("userAgent", "Context2D/1.1");
       
   354     navigator.setProperty("userLanguage", "en_US");
       
   355     self.setProperty("navigator", navigator);
       
   356 
       
   357     m_engine->setGlobalObject(self);
       
   358 
       
   359     m_engine->collectGarbage();
       
   360 }
       
   361 
       
   362 QScriptValue Environment::evaluate(const QString &code, const QString &fileName)
       
   363 {
       
   364     return m_engine->evaluate(code, fileName);
       
   365 }
       
   366 
       
   367 //! [2]
       
   368 QScriptValue Environment::toWrapper(QObject *object)
       
   369 {
       
   370     return m_engine->newQObject(object, QScriptEngine::QtOwnership,
       
   371                                 QScriptEngine::PreferExistingWrapperObject
       
   372                                 | QScriptEngine::ExcludeSuperClassContents);
       
   373 }
       
   374 //! [2]
       
   375 
       
   376 //! [3]
       
   377 void Environment::handleEvent(QContext2DCanvas *canvas, QMouseEvent *e)
       
   378 {
       
   379     QString type;
       
   380     switch (e->type()) {
       
   381     case QEvent::MouseButtonPress:
       
   382         type = "mousedown"; break;
       
   383     case QEvent::MouseButtonRelease:
       
   384         type = "mouseup"; break;
       
   385     case QEvent::MouseMove:
       
   386         type = "mousemove"; break;
       
   387     default: break;
       
   388     }
       
   389     if (type.isEmpty())
       
   390         return;
       
   391 
       
   392     QScriptValue handlerObject;
       
   393     QScriptValue handler = eventHandler(canvas, type, &handlerObject);
       
   394     if (!handler.isFunction())
       
   395         return;
       
   396 
       
   397     QScriptValue scriptEvent = newFakeDomEvent(type, toWrapper(canvas));
       
   398     // MouseEvent
       
   399     scriptEvent.setProperty("screenX", e->globalX(), QScriptValue::ReadOnly);
       
   400     scriptEvent.setProperty("screenY", e->globalY(), QScriptValue::ReadOnly);
       
   401     scriptEvent.setProperty("clientX", e->x(), QScriptValue::ReadOnly);
       
   402     scriptEvent.setProperty("clientY", e->y(), QScriptValue::ReadOnly);
       
   403     scriptEvent.setProperty("layerX", e->x(), QScriptValue::ReadOnly);
       
   404     scriptEvent.setProperty("layerY", e->y(), QScriptValue::ReadOnly);
       
   405     scriptEvent.setProperty("pageX", e->x(), QScriptValue::ReadOnly);
       
   406     scriptEvent.setProperty("pageY", e->y(), QScriptValue::ReadOnly);
       
   407     scriptEvent.setProperty("altKey", (e->modifiers() & Qt::AltModifier) != 0,
       
   408                             QScriptValue::ReadOnly);
       
   409     scriptEvent.setProperty("ctrlKey", (e->modifiers() & Qt::ControlModifier) != 0,
       
   410                             QScriptValue::ReadOnly);
       
   411     scriptEvent.setProperty("metaKey", (e->modifiers() & Qt::MetaModifier) != 0,
       
   412                             QScriptValue::ReadOnly);
       
   413     scriptEvent.setProperty("shiftKey", (e->modifiers() & Qt::ShiftModifier) != 0,
       
   414                             QScriptValue::ReadOnly);
       
   415     int button = 0;
       
   416     if (e->button() == Qt::RightButton)
       
   417         button = 2;
       
   418     else if (e->button() == Qt::MidButton)
       
   419         button = 1;
       
   420     scriptEvent.setProperty("button", button);
       
   421     scriptEvent.setProperty("relatedTarget", m_engine->nullValue(),
       
   422                             QScriptValue::ReadOnly);
       
   423     handler.call(handlerObject, QScriptValueList() << scriptEvent);
       
   424     maybeEmitScriptError();
       
   425 }
       
   426 //! [3]
       
   427 
       
   428 void Environment::handleEvent(QContext2DCanvas *canvas, QKeyEvent *e)
       
   429 {
       
   430     QString type;
       
   431     switch (e->type()) {
       
   432     case QEvent::KeyPress:
       
   433         type = "keydown"; break;
       
   434     case QEvent::KeyRelease:
       
   435         type = "keyup"; break;
       
   436     default: break;
       
   437     }
       
   438     if (type.isEmpty())
       
   439         return;
       
   440 
       
   441     QScriptValue handlerObject;
       
   442     QScriptValue handler = eventHandler(canvas, type, &handlerObject);
       
   443     if (!handler.isFunction())
       
   444         return;
       
   445 
       
   446     QScriptValue scriptEvent = newFakeDomEvent(type, toWrapper(canvas));
       
   447     // KeyEvent
       
   448     scriptEvent.setProperty("isChar", !e->text().isEmpty());
       
   449     scriptEvent.setProperty("charCode", e->text());
       
   450     scriptEvent.setProperty("keyCode", FakeDomEvent::qtToDomKey(e->key()));
       
   451     scriptEvent.setProperty("which", e->key());
       
   452 
       
   453     handler.call(handlerObject, QScriptValueList() << scriptEvent);
       
   454     maybeEmitScriptError();
       
   455 }
       
   456 
       
   457 QScriptValue Environment::eventHandler(QContext2DCanvas *canvas, const QString &type,
       
   458                                        QScriptValue *who)
       
   459 {
       
   460     QString handlerName = "on" + type;
       
   461     QScriptValue obj = toWrapper(canvas);
       
   462     QScriptValue handler = obj.property(handlerName);
       
   463     if (!handler.isValid()) {
       
   464         obj = m_document;
       
   465         handler = obj.property(handlerName);
       
   466     }
       
   467     if (who && handler.isFunction())
       
   468         *who = obj;
       
   469     return handler;
       
   470 }
       
   471 
       
   472 //! [4]
       
   473 QScriptValue Environment::newFakeDomEvent(const QString &type, const QScriptValue &target)
       
   474 {
       
   475     QScriptValue e = m_engine->newObject();
       
   476     // Event
       
   477     e.setProperty("type", type, QScriptValue::ReadOnly);
       
   478     e.setProperty("bubbles", true, QScriptValue::ReadOnly);
       
   479     e.setProperty("cancelable", false, QScriptValue::ReadOnly);
       
   480     e.setProperty("target", target, QScriptValue::ReadOnly);
       
   481     e.setProperty("currentTarget", target, QScriptValue::ReadOnly);
       
   482     e.setProperty("eventPhase", 3); // bubbling
       
   483     e.setProperty("timeStamp", QDateTime::currentDateTime().toTime_t());
       
   484     // UIEvent
       
   485     e.setProperty("detail", 0, QScriptValue::ReadOnly);
       
   486     e.setProperty("view", m_engine->globalObject(), QScriptValue::ReadOnly);
       
   487     return e;
       
   488 }
       
   489 //! [4]
       
   490 
       
   491 void Environment::maybeEmitScriptError()
       
   492 {
       
   493     if (m_engine->hasUncaughtException())
       
   494         emit scriptError(m_engine->uncaughtException());
       
   495 }
       
   496 
       
   497 
       
   498 Document::Document(Environment *env)
       
   499     : QObject(env)
       
   500 {
       
   501 }
       
   502 
       
   503 Document::~Document()
       
   504 {
       
   505 }
       
   506 
       
   507 QScriptValue Document::getElementById(const QString &id) const
       
   508 {
       
   509     Environment *env = qobject_cast<Environment*>(parent());
       
   510     QContext2DCanvas *canvas = env->canvasByName(id);
       
   511     if (!canvas)
       
   512         return QScriptValue();
       
   513     return env->toWrapper(canvas);
       
   514 }
       
   515 
       
   516 QScriptValue Document::getElementsByTagName(const QString &name) const
       
   517 {
       
   518     if (name != "canvas")
       
   519         return QScriptValue();
       
   520     Environment *env = qobject_cast<Environment*>(parent());
       
   521     QList<QContext2DCanvas*> list = env->canvases();
       
   522     QScriptValue result = env->engine()->newArray(list.size());
       
   523     for (int i = 0; i < list.size(); ++i)
       
   524         result.setProperty(i, env->toWrapper(list.at(i)));
       
   525     return result;
       
   526 }
       
   527 
       
   528 void Document::addEventListener(const QString &type, const QScriptValue &listener,
       
   529                                 bool useCapture)
       
   530 {
       
   531     Q_UNUSED(useCapture);
       
   532     if (listener.isFunction()) {
       
   533         Environment *env = qobject_cast<Environment*>(parent());
       
   534         QScriptValue self = env->toWrapper(this);
       
   535         self.setProperty("on" + type, listener);
       
   536     }
       
   537 }
       
   538 
       
   539 
       
   540 QColor colorFromString(const QString &name);
       
   541 
       
   542 CanvasGradientPrototype::CanvasGradientPrototype(QObject *parent)
       
   543     : QObject(parent)
       
   544 {
       
   545 }
       
   546 
       
   547 void CanvasGradientPrototype::addColorStop(qreal offset, const QString &color)
       
   548 {
       
   549     CanvasGradient *self = qscriptvalue_cast<CanvasGradient*>(thisObject());
       
   550     if (!self || (self->value.type() == QGradient::NoGradient))
       
   551         return;
       
   552     self->value.setColorAt(offset, colorFromString(color));
       
   553 }
       
   554 
       
   555 void CanvasGradientPrototype::setup(QScriptEngine *engine)
       
   556 {
       
   557     CanvasGradientPrototype *proto = new CanvasGradientPrototype();
       
   558     engine->setDefaultPrototype(qMetaTypeId<CanvasGradient>(),
       
   559         engine->newQObject(proto, QScriptEngine::ScriptOwnership,
       
   560                            QScriptEngine::ExcludeSuperClassContents));
       
   561 }