summaryrefslogtreecommitdiffstats
path: root/examples/script/context2d
diff options
context:
space:
mode:
Diffstat (limited to 'examples/script/context2d')
-rw-r--r--examples/script/context2d/context2d.cpp825
-rw-r--r--examples/script/context2d/context2d.h261
-rw-r--r--examples/script/context2d/context2d.pro23
-rw-r--r--examples/script/context2d/context2d.qrc5
-rw-r--r--examples/script/context2d/domimage.cpp157
-rw-r--r--examples/script/context2d/domimage.h87
-rw-r--r--examples/script/context2d/environment.cpp561
-rw-r--r--examples/script/context2d/environment.h145
-rw-r--r--examples/script/context2d/main.cpp53
-rw-r--r--examples/script/context2d/qcontext2dcanvas.cpp143
-rw-r--r--examples/script/context2d/qcontext2dcanvas.h98
-rw-r--r--examples/script/context2d/scripts/alpha.js21
-rw-r--r--examples/script/context2d/scripts/arc.js30
-rw-r--r--examples/script/context2d/scripts/bezier.js26
-rw-r--r--examples/script/context2d/scripts/clock.js99
-rw-r--r--examples/script/context2d/scripts/fill1.js8
-rw-r--r--examples/script/context2d/scripts/grad.js20
-rw-r--r--examples/script/context2d/scripts/linecap.js24
-rw-r--r--examples/script/context2d/scripts/linestye.js10
-rw-r--r--examples/script/context2d/scripts/moveto.js20
-rw-r--r--examples/script/context2d/scripts/moveto2.js24
-rw-r--r--examples/script/context2d/scripts/pacman.js83
-rw-r--r--examples/script/context2d/scripts/plasma.js58
-rw-r--r--examples/script/context2d/scripts/pong.js235
-rw-r--r--examples/script/context2d/scripts/quad.js21
-rw-r--r--examples/script/context2d/scripts/rgba.js19
-rw-r--r--examples/script/context2d/scripts/rotate.js16
-rw-r--r--examples/script/context2d/scripts/scale.js67
-rw-r--r--examples/script/context2d/scripts/stroke1.js10
-rw-r--r--examples/script/context2d/scripts/translate.js29
-rw-r--r--examples/script/context2d/window.cpp174
-rw-r--r--examples/script/context2d/window.h81
32 files changed, 3433 insertions, 0 deletions
diff --git a/examples/script/context2d/context2d.cpp b/examples/script/context2d/context2d.cpp
new file mode 100644
index 0000000..d49cc3d
--- /dev/null
+++ b/examples/script/context2d/context2d.cpp
@@ -0,0 +1,825 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "context2d.h"
+
+#include <QVariant>
+
+#include <math.h>
+static const double Q_PI = 3.14159265358979323846; // pi
+
+#define DEGREES(t) ((t) * 180.0 / Q_PI)
+
+#define qClamp(val, min, max) qMin(qMax(val, min), max)
+static QList<qreal> parseNumbersList(QString::const_iterator &itr)
+{
+ QList<qreal> points;
+ QString temp;
+ while ((*itr).isSpace())
+ ++itr;
+ while ((*itr).isNumber() ||
+ (*itr) == '-' || (*itr) == '+' || (*itr) == '.') {
+ temp = QString();
+
+ if ((*itr) == '-')
+ temp += *itr++;
+ else if ((*itr) == '+')
+ temp += *itr++;
+ while ((*itr).isDigit())
+ temp += *itr++;
+ if ((*itr) == '.')
+ temp += *itr++;
+ while ((*itr).isDigit())
+ temp += *itr++;
+ while ((*itr).isSpace())
+ ++itr;
+ if ((*itr) == ',')
+ ++itr;
+ points.append(temp.toDouble());
+ //eat spaces
+ while ((*itr).isSpace())
+ ++itr;
+ }
+
+ return points;
+}
+
+QColor colorFromString(const QString &name)
+{
+ QString::const_iterator itr = name.constBegin();
+ QList<qreal> compo;
+ if (name.startsWith("rgba(")) {
+ ++itr; ++itr; ++itr; ++itr; ++itr;
+ compo = parseNumbersList(itr);
+ if (compo.size() != 4) {
+ return QColor();
+ }
+ //alpha seems to be always between 0-1
+ compo[3] *= 255;
+ return QColor((int)compo[0], (int)compo[1],
+ (int)compo[2], (int)compo[3]);
+ } else if (name.startsWith("rgb(")) {
+ ++itr; ++itr; ++itr; ++itr;
+ compo = parseNumbersList(itr);
+ if (compo.size() != 3) {
+ return QColor();
+ }
+ return QColor((int)qClamp(compo[0], qreal(0), qreal(255)),
+ (int)qClamp(compo[1], qreal(0), qreal(255)),
+ (int)qClamp(compo[2], qreal(0), qreal(255)));
+ } else {
+ //QRgb color;
+ //CSSParser::parseColor(name, color);
+ return QColor(name);
+ }
+}
+
+
+static QPainter::CompositionMode compositeOperatorFromString(const QString &compositeOperator)
+{
+ if ( compositeOperator == "source-over" ) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if ( compositeOperator == "source-out" ) {
+ return QPainter::CompositionMode_SourceOut;
+ } else if ( compositeOperator == "source-in" ) {
+ return QPainter::CompositionMode_SourceIn;
+ } else if ( compositeOperator == "source-atop" ) {
+ return QPainter::CompositionMode_SourceAtop;
+ } else if ( compositeOperator == "destination-atop" ) {
+ return QPainter::CompositionMode_DestinationAtop;
+ } else if ( compositeOperator == "destination-in" ) {
+ return QPainter::CompositionMode_DestinationIn;
+ } else if ( compositeOperator == "destination-out" ) {
+ return QPainter::CompositionMode_DestinationOut;
+ } else if ( compositeOperator == "destination-over" ) {
+ return QPainter::CompositionMode_DestinationOver;
+ } else if ( compositeOperator == "darker" ) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if ( compositeOperator == "lighter" ) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if ( compositeOperator == "copy" ) {
+ return QPainter::CompositionMode_Source;
+ } else if ( compositeOperator == "xor" ) {
+ return QPainter::CompositionMode_Xor;
+ }
+
+ return QPainter::CompositionMode_SourceOver;
+}
+
+static QString compositeOperatorToString(QPainter::CompositionMode op)
+{
+ switch (op) {
+ case QPainter::CompositionMode_SourceOver:
+ return "source-over";
+ case QPainter::CompositionMode_DestinationOver:
+ return "destination-over";
+ case QPainter::CompositionMode_Clear:
+ return "clear";
+ case QPainter::CompositionMode_Source:
+ return "source";
+ case QPainter::CompositionMode_Destination:
+ return "destination";
+ case QPainter::CompositionMode_SourceIn:
+ return "source-in";
+ case QPainter::CompositionMode_DestinationIn:
+ return "destination-in";
+ case QPainter::CompositionMode_SourceOut:
+ return "source-out";
+ case QPainter::CompositionMode_DestinationOut:
+ return "destination-out";
+ case QPainter::CompositionMode_SourceAtop:
+ return "source-atop";
+ case QPainter::CompositionMode_DestinationAtop:
+ return "destination-atop";
+ case QPainter::CompositionMode_Xor:
+ return "xor";
+ case QPainter::CompositionMode_Plus:
+ return "plus";
+ case QPainter::CompositionMode_Multiply:
+ return "multiply";
+ case QPainter::CompositionMode_Screen:
+ return "screen";
+ case QPainter::CompositionMode_Overlay:
+ return "overlay";
+ case QPainter::CompositionMode_Darken:
+ return "darken";
+ case QPainter::CompositionMode_Lighten:
+ return "lighten";
+ case QPainter::CompositionMode_ColorDodge:
+ return "color-dodge";
+ case QPainter::CompositionMode_ColorBurn:
+ return "color-burn";
+ case QPainter::CompositionMode_HardLight:
+ return "hard-light";
+ case QPainter::CompositionMode_SoftLight:
+ return "soft-light";
+ case QPainter::CompositionMode_Difference:
+ return "difference";
+ case QPainter::CompositionMode_Exclusion:
+ return "exclusion";
+ default:
+ break;
+ }
+ return QString();
+}
+
+void Context2D::save()
+{
+ m_stateStack.push(m_state);
+}
+
+
+void Context2D::restore()
+{
+ if (!m_stateStack.isEmpty()) {
+ m_state = m_stateStack.pop();
+ m_state.flags = AllIsFullOfDirt;
+ }
+}
+
+
+void Context2D::scale(qreal x, qreal y)
+{
+ m_state.matrix.scale(x, y);
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::rotate(qreal angle)
+{
+ m_state.matrix.rotate(DEGREES(angle));
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::translate(qreal x, qreal y)
+{
+ m_state.matrix.translate(x, y);
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::transform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy)
+{
+ QMatrix mat(m11, m12,
+ m21, m22,
+ dx, dy);
+ m_state.matrix *= mat;
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+void Context2D::setTransform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy)
+{
+ QMatrix mat(m11, m12,
+ m21, m22,
+ dx, dy);
+ m_state.matrix = mat;
+ m_state.flags |= DirtyTransformationMatrix;
+}
+
+
+QString Context2D::globalCompositeOperation() const
+{
+ return compositeOperatorToString(m_state.globalCompositeOperation);
+}
+
+void Context2D::setGlobalCompositeOperation(const QString &op)
+{
+ QPainter::CompositionMode mode =
+ compositeOperatorFromString(op);
+ m_state.globalCompositeOperation = mode;
+ m_state.flags |= DirtyGlobalCompositeOperation;
+}
+
+QVariant Context2D::strokeStyle() const
+{
+ return m_state.strokeStyle;
+}
+
+void Context2D::setStrokeStyle(const QVariant &style)
+{
+ if (qVariantCanConvert<CanvasGradient>(style)) {
+ CanvasGradient cg = qvariant_cast<CanvasGradient>(style);
+ m_state.strokeStyle = cg.value;
+ } else {
+ QColor color = colorFromString(style.toString());
+ m_state.strokeStyle = color;
+ }
+ m_state.flags |= DirtyStrokeStyle;
+}
+
+QVariant Context2D::fillStyle() const
+{
+ return m_state.fillStyle;
+}
+
+//! [3]
+void Context2D::setFillStyle(const QVariant &style)
+{
+ if (qVariantCanConvert<CanvasGradient>(style)) {
+ CanvasGradient cg = qvariant_cast<CanvasGradient>(style);
+ m_state.fillStyle = cg.value;
+ } else {
+ QColor color = colorFromString(style.toString());
+ m_state.fillStyle = color;
+ }
+ m_state.flags |= DirtyFillStyle;
+}
+//! [3]
+
+qreal Context2D::globalAlpha() const
+{
+ return m_state.globalAlpha;
+}
+
+void Context2D::setGlobalAlpha(qreal alpha)
+{
+ m_state.globalAlpha = alpha;
+ m_state.flags |= DirtyGlobalAlpha;
+}
+
+
+CanvasGradient Context2D::createLinearGradient(qreal x0, qreal y0,
+ qreal x1, qreal y1)
+{
+ QLinearGradient g(x0, y0, x1, y1);
+ return CanvasGradient(g);
+}
+
+
+CanvasGradient Context2D::createRadialGradient(qreal x0, qreal y0,
+ qreal r0, qreal x1,
+ qreal y1, qreal r1)
+{
+ QRadialGradient g(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
+ return CanvasGradient(g);
+}
+
+qreal Context2D::lineWidth() const
+{
+ return m_state.lineWidth;
+}
+
+void Context2D::setLineWidth(qreal w)
+{
+ m_state.lineWidth = w;
+ m_state.flags |= DirtyLineWidth;
+}
+
+//! [0]
+QString Context2D::lineCap() const
+{
+ switch (m_state.lineCap) {
+ case Qt::FlatCap:
+ return "butt";
+ case Qt::SquareCap:
+ return "square";
+ case Qt::RoundCap:
+ return "round";
+ default: ;
+ }
+ return QString();
+}
+
+void Context2D::setLineCap(const QString &capString)
+{
+ Qt::PenCapStyle style;
+ if (capString == "round")
+ style = Qt::RoundCap;
+ else if (capString == "square")
+ style = Qt::SquareCap;
+ else if (capString == "butt")
+ style = Qt::FlatCap;
+ m_state.lineCap = style;
+ m_state.flags |= DirtyLineCap;
+}
+//! [0]
+
+QString Context2D::lineJoin() const
+{
+ switch (m_state.lineJoin) {
+ case Qt::RoundJoin:
+ return "round";
+ case Qt::BevelJoin:
+ return "bevel";
+ case Qt::MiterJoin:
+ return "miter";
+ default: ;
+ }
+ return QString();
+}
+
+void Context2D::setLineJoin(const QString &joinString)
+{
+ Qt::PenJoinStyle style;
+ if (joinString == "round")
+ style = Qt::RoundJoin;
+ else if (joinString == "bevel")
+ style = Qt::BevelJoin;
+ else if (joinString == "miter")
+ style = Qt::MiterJoin;
+ m_state.lineJoin = style;
+ m_state.flags |= DirtyLineJoin;
+}
+
+qreal Context2D::miterLimit() const
+{
+ return m_state.miterLimit;
+}
+
+void Context2D::setMiterLimit(qreal m)
+{
+ m_state.miterLimit = m;
+ m_state.flags |= DirtyMiterLimit;
+}
+
+void Context2D::setShadowOffsetX(qreal x)
+{
+ m_state.shadowOffsetX = x;
+ m_state.flags |= DirtyShadowOffsetX;
+}
+
+void Context2D::setShadowOffsetY(qreal y)
+{
+ m_state.shadowOffsetY = y;
+ m_state.flags |= DirtyShadowOffsetY;
+}
+
+void Context2D::setShadowBlur(qreal b)
+{
+ m_state.shadowBlur = b;
+ m_state.flags |= DirtyShadowBlur;
+}
+
+void Context2D::setShadowColor(const QString &str)
+{
+ m_state.shadowColor = colorFromString(str);
+ m_state.flags |= DirtyShadowColor;
+}
+
+qreal Context2D::shadowOffsetX() const
+{
+ return m_state.shadowOffsetX;
+}
+
+qreal Context2D::shadowOffsetY() const
+{
+ return m_state.shadowOffsetY;
+}
+
+
+qreal Context2D::shadowBlur() const
+{
+ return m_state.shadowBlur;
+}
+
+
+QString Context2D::shadowColor() const
+{
+ return m_state.shadowColor.name();
+}
+
+
+void Context2D::clearRect(qreal x, qreal y, qreal w, qreal h)
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(m_state.matrix, false);
+ m_painter.setCompositionMode(QPainter::CompositionMode_Source);
+ m_painter.fillRect(QRectF(x, y, w, h), QColor(0, 0, 0, 0));
+ m_painter.restore();
+ scheduleChange();
+}
+
+
+//! [1]
+void Context2D::fillRect(qreal x, qreal y, qreal w, qreal h)
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(m_state.matrix, false);
+ m_painter.fillRect(QRectF(x, y, w, h), m_painter.brush());
+ m_painter.restore();
+ scheduleChange();
+}
+//! [1]
+
+
+void Context2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path;
+ path.addRect(x, y, w, h);
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(m_state.matrix, false);
+ m_painter.strokePath(path, m_painter.pen());
+ m_painter.restore();
+ scheduleChange();
+}
+
+
+void Context2D::beginPath()
+{
+ m_path = QPainterPath();
+}
+
+
+void Context2D::closePath()
+{
+ m_path.closeSubpath();
+}
+
+
+void Context2D::moveTo(qreal x, qreal y)
+{
+ QPointF pt = m_state.matrix.map(QPointF(x, y));
+ m_path.moveTo(pt);
+}
+
+
+void Context2D::lineTo(qreal x, qreal y)
+{
+ QPointF pt = m_state.matrix.map(QPointF(x, y));
+ m_path.lineTo(pt);
+}
+
+
+void Context2D::quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y)
+{
+ QPointF cp = m_state.matrix.map(QPointF(cpx, cpy));
+ QPointF xy = m_state.matrix.map(QPointF(x, y));
+ m_path.quadTo(cp, xy);
+}
+
+
+void Context2D::bezierCurveTo(qreal cp1x, qreal cp1y,
+ qreal cp2x, qreal cp2y, qreal x, qreal y)
+{
+ QPointF cp1 = m_state.matrix.map(QPointF(cp1x, cp1y));
+ QPointF cp2 = m_state.matrix.map(QPointF(cp2x, cp2y));
+ QPointF end = m_state.matrix.map(QPointF(x, y));
+ m_path.cubicTo(cp1, cp2, end);
+}
+
+
+void Context2D::arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius)
+{
+ //FIXME: this is surely busted
+ QPointF st = m_state.matrix.map(QPointF(x1, y1));
+ QPointF end = m_state.matrix.map(QPointF(x2, y2));
+ m_path.arcTo(st.x(), st.y(),
+ end.x()-st.x(), end.y()-st.y(),
+ radius, 90);
+}
+
+
+void Context2D::rect(qreal x, qreal y, qreal w, qreal h)
+{
+ QPainterPath path; path.addRect(x, y, w, h);
+ path = m_state.matrix.map(path);
+ m_path.addPath(path);
+}
+
+void Context2D::arc(qreal xc, qreal yc, qreal radius,
+ qreal sar, qreal ear,
+ bool anticlockwise)
+{
+ //### HACK
+ // In Qt we don't switch the coordinate system for degrees
+ // and still use the 0,0 as bottom left for degrees so we need
+ // to switch
+ sar = -sar;
+ ear = -ear;
+ anticlockwise = !anticlockwise;
+ //end hack
+
+ float sa = DEGREES(sar);
+ float ea = DEGREES(ear);
+
+ double span = 0;
+
+ double xs = xc - radius;
+ double ys = yc - radius;
+ double width = radius*2;
+ double height = radius*2;
+
+ if (!anticlockwise && (ea < sa)) {
+ span += 360;
+ } else if (anticlockwise && (sa < ea)) {
+ span -= 360;
+ }
+
+ //### this is also due to switched coordinate system
+ // we would end up with a 0 span instead of 360
+ if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) &&
+ qFuzzyCompare(qAbs(span), 360))) {
+ span += ea - sa;
+ }
+
+ QPainterPath path;
+ path.moveTo(QPointF(xc + radius * cos(sar),
+ yc - radius * sin(sar)));
+
+ path.arcTo(xs, ys, width, height, sa, span);
+ path = m_state.matrix.map(path);
+ m_path.addPath(path);
+}
+
+
+void Context2D::fill()
+{
+ beginPainting();
+ m_painter.fillPath(m_path, m_painter.brush());
+ scheduleChange();
+}
+
+
+void Context2D::stroke()
+{
+ beginPainting();
+ m_painter.save();
+ m_painter.setMatrix(m_state.matrix, false);
+ QPainterPath tmp = m_state.matrix.inverted().map(m_path);
+ m_painter.strokePath(tmp, m_painter.pen());
+ m_painter.restore();
+ scheduleChange();
+}
+
+
+void Context2D::clip()
+{
+ m_state.clipPath = m_path;
+ m_state.flags |= DirtyClippingRegion;
+}
+
+
+bool Context2D::isPointInPath(qreal x, qreal y) const
+{
+ return m_path.contains(QPointF(x, y));
+}
+
+
+ImageData Context2D::getImageData(qreal sx, qreal sy, qreal sw, qreal sh)
+{
+ Q_UNUSED(sx);
+ Q_UNUSED(sy);
+ Q_UNUSED(sw);
+ Q_UNUSED(sh);
+ return ImageData();
+}
+
+
+void Context2D::putImageData(ImageData image, qreal dx, qreal dy)
+{
+ Q_UNUSED(image);
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+}
+
+Context2D::Context2D(QObject *parent)
+ : QObject(parent), m_changeTimerId(-1)
+{
+ reset();
+}
+
+const QImage &Context2D::endPainting()
+{
+ if (m_painter.isActive())
+ m_painter.end();
+ return m_image;
+}
+
+void Context2D::beginPainting()
+{
+ if (!m_painter.isActive()) {
+ m_painter.begin(&m_image);
+ m_painter.setRenderHint(QPainter::Antialiasing);
+ if (!m_state.clipPath.isEmpty())
+ m_painter.setClipPath(m_state.clipPath);
+ m_painter.setBrush(m_state.fillStyle);
+ m_painter.setOpacity(m_state.globalAlpha);
+ QPen pen;
+ pen.setBrush(m_state.strokeStyle);
+ if (pen.style() == Qt::NoPen)
+ pen.setStyle(Qt::SolidLine);
+ pen.setCapStyle(m_state.lineCap);
+ pen.setJoinStyle(m_state.lineJoin);
+ pen.setWidthF(m_state.lineWidth);
+ pen.setMiterLimit(m_state.miterLimit);
+ m_painter.setPen(pen);
+ } else {
+ if ((m_state.flags & DirtyClippingRegion) && !m_state.clipPath.isEmpty())
+ m_painter.setClipPath(m_state.clipPath);
+ if (m_state.flags & DirtyFillStyle)
+ m_painter.setBrush(m_state.fillStyle);
+ if (m_state.flags & DirtyGlobalAlpha)
+ m_painter.setOpacity(m_state.globalAlpha);
+ if (m_state.flags & DirtyGlobalCompositeOperation)
+ m_painter.setCompositionMode(m_state.globalCompositeOperation);
+ if (m_state.flags & MDirtyPen) {
+ QPen pen = m_painter.pen();
+ if (m_state.flags & DirtyStrokeStyle)
+ pen.setBrush(m_state.strokeStyle);
+ if (m_state.flags & DirtyLineWidth)
+ pen.setWidthF(m_state.lineWidth);
+ if (m_state.flags & DirtyLineCap)
+ pen.setCapStyle(m_state.lineCap);
+ if (m_state.flags & DirtyLineJoin)
+ pen.setJoinStyle(m_state.lineJoin);
+ if (m_state.flags & DirtyMiterLimit)
+ pen.setMiterLimit(m_state.miterLimit);
+ m_painter.setPen(pen);
+ }
+ m_state.flags = 0;
+ }
+}
+
+void Context2D::clear()
+{
+ endPainting();
+ m_image.fill(qRgba(0,0,0,0));
+ scheduleChange();
+}
+
+void Context2D::reset()
+{
+ m_stateStack.clear();
+ m_state.matrix = QMatrix();
+ m_state.clipPath = QPainterPath();
+ m_state.globalAlpha = 1.0;
+ m_state.globalCompositeOperation = QPainter::CompositionMode_SourceOver;
+ m_state.strokeStyle = Qt::black;
+ m_state.fillStyle = Qt::black;
+ m_state.lineWidth = 1;
+ m_state.lineCap = Qt::FlatCap;
+ m_state.lineJoin = Qt::MiterJoin;
+ m_state.miterLimit = 10;
+ m_state.shadowOffsetX = 0;
+ m_state.shadowOffsetY = 0;
+ m_state.shadowBlur = 0;
+ m_state.shadowColor = qRgba(0, 0, 0, 0);
+ m_state.flags = AllIsFullOfDirt;
+ clear();
+}
+
+void Context2D::setSize(int width, int height)
+{
+ endPainting();
+ QImage newi(width, height, QImage::Format_ARGB32_Premultiplied);
+ newi.fill(qRgba(0,0,0,0));
+ QPainter p(&newi);
+ p.drawImage(0, 0, m_image);
+ p.end();
+ m_image = newi;
+ scheduleChange();
+}
+
+void Context2D::setSize(const QSize &size)
+{
+ setSize(size.width(), size.height());
+}
+
+QSize Context2D::size() const
+{
+ return m_image.size();
+}
+
+void Context2D::drawImage(DomImage *image, qreal dx, qreal dy)
+{
+ if (!image)
+ return;
+ if (dx < 0) {
+ qreal sx = qAbs(dx);
+ qreal sy = qAbs(dy);
+ qreal sw = image->width() - sx;
+ qreal sh = image->height() - sy;
+
+ drawImage(image, sx, sy, sw, sh, 0, 0, sw, sh);
+ } else {
+ beginPainting();
+ m_painter.drawImage(QPointF(dx, dy), image->image());
+ scheduleChange();
+ }
+}
+
+void Context2D::drawImage(DomImage *image, qreal dx, qreal dy,
+ qreal dw, qreal dh)
+{
+ if (!image)
+ return;
+ beginPainting();
+ m_painter.drawImage(QRectF(dx, dy, dw, dh).toRect(), image->image());
+ scheduleChange();
+}
+
+void Context2D::drawImage(DomImage *image, qreal sx, qreal sy,
+ qreal sw, qreal sh, qreal dx, qreal dy,
+ qreal dw, qreal dh)
+{
+ if (!image)
+ return;
+ beginPainting();
+ m_painter.drawImage(QRectF(dx, dy, dw, dh), image->image(),
+ QRectF(sx, sy, sw, sh));
+ scheduleChange();
+}
+
+//! [2]
+void Context2D::scheduleChange()
+{
+ if (m_changeTimerId == -1)
+ m_changeTimerId = startTimer(0);
+}
+
+void Context2D::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == m_changeTimerId) {
+ killTimer(m_changeTimerId);
+ m_changeTimerId = -1;
+ emit changed(endPainting());
+ } else {
+ QObject::timerEvent(e);
+ }
+}
+//! [2]
diff --git a/examples/script/context2d/context2d.h b/examples/script/context2d/context2d.h
new file mode 100644
index 0000000..38188f7
--- /dev/null
+++ b/examples/script/context2d/context2d.h
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTEXT2D_H
+#define CONTEXT2D_H
+
+#include "domimage.h"
+
+#include <QPainter>
+#include <QPainterPath>
+#include <QString>
+#include <QStack>
+#include <QMetaType>
+#include <QTimerEvent>
+
+// [3]
+class CanvasGradient
+{
+public:
+ CanvasGradient(const QGradient &v)
+ : value(v) {}
+ CanvasGradient() {}
+
+ QGradient value;
+};
+// [3]
+
+Q_DECLARE_METATYPE(CanvasGradient)
+Q_DECLARE_METATYPE(CanvasGradient*)
+
+class ImageData {
+};
+
+class QContext2DCanvas;
+
+//! [0]
+class Context2D : public QObject
+{
+ Q_OBJECT
+ // compositing
+ Q_PROPERTY(qreal globalAlpha READ globalAlpha WRITE setGlobalAlpha)
+ Q_PROPERTY(QString globalCompositeOperation READ globalCompositeOperation WRITE setGlobalCompositeOperation)
+ Q_PROPERTY(QVariant strokeStyle READ strokeStyle WRITE setStrokeStyle)
+ Q_PROPERTY(QVariant fillStyle READ fillStyle WRITE setFillStyle)
+ // line caps/joins
+ Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth)
+ Q_PROPERTY(QString lineCap READ lineCap WRITE setLineCap)
+ Q_PROPERTY(QString lineJoin READ lineJoin WRITE setLineJoin)
+ Q_PROPERTY(qreal miterLimit READ miterLimit WRITE setMiterLimit)
+ // shadows
+ Q_PROPERTY(qreal shadowOffsetX READ shadowOffsetX WRITE setShadowOffsetX)
+ Q_PROPERTY(qreal shadowOffsetY READ shadowOffsetY WRITE setShadowOffsetY)
+ Q_PROPERTY(qreal shadowBlur READ shadowBlur WRITE setShadowBlur)
+ Q_PROPERTY(QString shadowColor READ shadowColor WRITE setShadowColor)
+//! [0]
+
+public:
+ Context2D(QObject *parent = 0);
+ void setSize(int width, int height);
+ void setSize(const QSize &size);
+ QSize size() const;
+
+ void clear();
+ void reset();
+
+ // compositing
+ qreal globalAlpha() const; // (default 1.0)
+ QString globalCompositeOperation() const; // (default over)
+ QVariant strokeStyle() const; // (default black)
+ QVariant fillStyle() const; // (default black)
+
+ void setGlobalAlpha(qreal alpha);
+ void setGlobalCompositeOperation(const QString &op);
+ void setStrokeStyle(const QVariant &style);
+ void setFillStyle(const QVariant &style);
+
+ // line caps/joins
+ qreal lineWidth() const; // (default 1)
+ QString lineCap() const; // "butt", "round", "square" (default "butt")
+ QString lineJoin() const; // "round", "bevel", "miter" (default "miter")
+ qreal miterLimit() const; // (default 10)
+
+ void setLineWidth(qreal w);
+ void setLineCap(const QString &s);
+ void setLineJoin(const QString &s);
+ void setMiterLimit(qreal m);
+
+ // shadows
+ qreal shadowOffsetX() const; // (default 0)
+ qreal shadowOffsetY() const; // (default 0)
+ qreal shadowBlur() const; // (default 0)
+ QString shadowColor() const; // (default black)
+
+ void setShadowOffsetX(qreal x);
+ void setShadowOffsetY(qreal y);
+ void setShadowBlur(qreal b);
+ void setShadowColor(const QString &str);
+
+//! [1]
+public slots:
+ void save(); // push state on state stack
+ void restore(); // pop state stack and restore state
+
+ void scale(qreal x, qreal y);
+ void rotate(qreal angle);
+ void translate(qreal x, qreal y);
+ void transform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy);
+ void setTransform(qreal m11, qreal m12, qreal m21, qreal m22,
+ qreal dx, qreal dy);
+
+ CanvasGradient createLinearGradient(qreal x0, qreal y0,
+ qreal x1, qreal y1);
+ CanvasGradient createRadialGradient(qreal x0, qreal y0,
+ qreal r0, qreal x1,
+ qreal y1, qreal r1);
+
+ // rects
+ void clearRect(qreal x, qreal y, qreal w, qreal h);
+ void fillRect(qreal x, qreal y, qreal w, qreal h);
+ void strokeRect(qreal x, qreal y, qreal w, qreal h);
+
+ // path API
+ void beginPath();
+ void closePath();
+ void moveTo(qreal x, qreal y);
+ void lineTo(qreal x, qreal y);
+ void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y);
+ void bezierCurveTo(qreal cp1x, qreal cp1y,
+ qreal cp2x, qreal cp2y, qreal x, qreal y);
+ void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius);
+ void rect(qreal x, qreal y, qreal w, qreal h);
+ void arc(qreal x, qreal y, qreal radius,
+ qreal startAngle, qreal endAngle,
+ bool anticlockwise);
+ void fill();
+ void stroke();
+ void clip();
+ bool isPointInPath(qreal x, qreal y) const;
+//! [1]
+
+ // drawing images
+ void drawImage(DomImage *image, qreal dx, qreal dy);
+ void drawImage(DomImage *image, qreal dx, qreal dy,
+ qreal dw, qreal dh);
+ void drawImage(DomImage *image, qreal sx, qreal sy,
+ qreal sw, qreal sh, qreal dx, qreal dy,
+ qreal dw, qreal dh);
+
+ // pixel manipulation
+ ImageData getImageData(qreal sx, qreal sy, qreal sw, qreal sh);
+ void putImageData(ImageData image, qreal dx, qreal dy);
+
+//! [2]
+signals:
+ void changed(const QImage &image);
+//! [2]
+
+protected:
+ void timerEvent(QTimerEvent *e);
+
+private:
+ void beginPainting();
+ const QImage &endPainting();
+ void scheduleChange();
+
+ int m_changeTimerId;
+ QImage m_image;
+ QPainter m_painter;
+ QPainterPath m_path;
+
+ enum DirtyFlag {
+ DirtyTransformationMatrix = 0x00001,
+ DirtyClippingRegion = 0x00002,
+ DirtyStrokeStyle = 0x00004,
+ DirtyFillStyle = 0x00008,
+ DirtyGlobalAlpha = 0x00010,
+ DirtyLineWidth = 0x00020,
+ DirtyLineCap = 0x00040,
+ DirtyLineJoin = 0x00080,
+ DirtyMiterLimit = 0x00100,
+ MDirtyPen = DirtyStrokeStyle
+ | DirtyLineWidth
+ | DirtyLineCap
+ | DirtyLineJoin
+ | DirtyMiterLimit,
+ DirtyShadowOffsetX = 0x00200,
+ DirtyShadowOffsetY = 0x00400,
+ DirtyShadowBlur = 0x00800,
+ DirtyShadowColor = 0x01000,
+ DirtyGlobalCompositeOperation = 0x2000,
+ DirtyFont = 0x04000,
+ DirtyTextAlign = 0x08000,
+ DirtyTextBaseline = 0x10000,
+ AllIsFullOfDirt = 0xfffff
+ };
+
+ struct State {
+ State() : flags(0) {}
+ QMatrix matrix;
+ QPainterPath clipPath;
+ QBrush strokeStyle;
+ QBrush fillStyle;
+ qreal globalAlpha;
+ qreal lineWidth;
+ Qt::PenCapStyle lineCap;
+ Qt::PenJoinStyle lineJoin;
+ qreal miterLimit;
+ qreal shadowOffsetX;
+ qreal shadowOffsetY;
+ qreal shadowBlur;
+ QColor shadowColor;
+ QPainter::CompositionMode globalCompositeOperation;
+ QFont font;
+ int textAlign;
+ int textBaseline;
+ int flags;
+ };
+ State m_state;
+ QStack<State> m_stateStack;
+};
+
+#endif
diff --git a/examples/script/context2d/context2d.pro b/examples/script/context2d/context2d.pro
new file mode 100644
index 0000000..30ec9a7
--- /dev/null
+++ b/examples/script/context2d/context2d.pro
@@ -0,0 +1,23 @@
+TEMPLATE = app
+QT += script
+# Input
+HEADERS += qcontext2dcanvas.h \
+ context2d.h \
+ domimage.h \
+ environment.h \
+ window.h
+SOURCES += qcontext2dcanvas.cpp \
+ context2d.cpp \
+ domimage.cpp \
+ environment.cpp \
+ window.cpp \
+ main.cpp
+RESOURCES += context2d.qrc
+
+contains(QT_CONFIG, scripttools): QT += scripttools
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/script/context2d
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS context2d.pro scripts
+sources.path = $$[QT_INSTALL_EXAMPLES]/script/context2d
+INSTALLS += target sources
diff --git a/examples/script/context2d/context2d.qrc b/examples/script/context2d/context2d.qrc
new file mode 100644
index 0000000..75e570c
--- /dev/null
+++ b/examples/script/context2d/context2d.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+ <file>scripts</file>
+</qresource>
+</RCC>
diff --git a/examples/script/context2d/domimage.cpp b/examples/script/context2d/domimage.cpp
new file mode 100644
index 0000000..66a2c95
--- /dev/null
+++ b/examples/script/context2d/domimage.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "domimage.h"
+
+#include <QVariant>
+
+#include <qscriptcontext.h>
+
+QScriptValue DomImage::s_self;
+
+DomImage::DomImage()
+{
+}
+
+
+int DomImage::width() const
+{
+ return m_image.width();
+}
+
+
+int DomImage::height() const
+{
+ return m_image.height();
+}
+
+
+QString DomImage::src() const
+{
+ return m_src;
+}
+
+void DomImage::setSrc(const QString &src)
+{
+ m_src = src;
+ m_image = QImage(m_src);
+}
+
+
+QString DomImage::name() const
+{
+ return m_src;
+}
+
+static QScriptValue Image(QScriptContext *context, QScriptEngine *env)
+{
+ QScriptValue val = context->thisObject();
+ DomImage *image = new DomImage();
+ QScriptValue klass = env->newVariant(qVariantFromValue(image));
+ klass.setPrototype(DomImage::s_self);
+ return klass;
+}
+
+
+static QScriptValue width(QScriptContext *context, QScriptEngine *)
+{
+ QScriptValue val = context->thisObject();
+
+ DomImage *image = qvariant_cast<DomImage*> (val.toVariant());
+ if (image)
+ return image->width();
+
+ return 0;
+}
+
+
+static QScriptValue height(QScriptContext *context, QScriptEngine *)
+{
+ QScriptValue val = context->thisObject();
+
+ DomImage *image = qvariant_cast<DomImage*> (val.toVariant());
+ if (image)
+ return image->height();
+
+ return 0;
+}
+
+
+static QScriptValue setSrc(QScriptContext *context, QScriptEngine *env)
+{
+ QScriptValue val = context->thisObject();
+ QString src = context->argument(0).toString();
+
+ DomImage *image = qvariant_cast<DomImage*> (val.toVariant());
+ if (image)
+ image->setSrc(src);
+
+ return env->undefinedValue();
+}
+
+
+static QScriptValue name(QScriptContext *context, QScriptEngine *)
+{
+ QScriptValue val = context->thisObject();
+
+ DomImage *image = qvariant_cast<DomImage*> (val.toVariant());
+ if (image)
+ return image->name();
+
+ return QString();
+}
+
+
+void DomImage::setup(QScriptEngine *e)
+{
+ qRegisterMetaType<DomImage>();
+
+ e->globalObject().setProperty("Image",
+ e->newFunction(::Image, 0));
+
+ s_self = e->newObject();
+ s_self.setProperty("setSrc", e->newFunction(&::setSrc, 1));
+ s_self.setProperty("width", e->newFunction(&::width));
+ s_self.setProperty("height", e->newFunction(&::height));
+ s_self.setProperty("name", e->newFunction(&::name));
+
+ e->setDefaultPrototype(qMetaTypeId<DomImage>(), s_self);
+}
diff --git a/examples/script/context2d/domimage.h b/examples/script/context2d/domimage.h
new file mode 100644
index 0000000..0793d1d
--- /dev/null
+++ b/examples/script/context2d/domimage.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DOMIMAGE_H
+#define DOMIMAGE_H
+
+#include <QPixmap>
+#include <QImage>
+#include <QMetaType>
+
+#include <qscriptengine.h>
+
+class DomImage
+{
+public:
+ DomImage();
+ static void setup(QScriptEngine *e);
+
+ int width() const;
+ int height() const;
+
+ QString src() const;
+ void setSrc(const QString &src);
+
+ QString name() const;
+
+ static QScriptValue s_self;
+
+ const QImage &image() const
+ {
+ return m_image;
+ }
+private:
+ QImage m_image;
+ QString m_src;
+ //attribute boolean isMap;
+ //attribute DOMString longDesc;
+ //attribute DOMString useMap;
+ //attribute DOMString align;
+ //attribute DOMString alt;
+ //attribute DOMString border;
+ //attribute long vspace;
+ //attribute long hspace;
+};
+
+Q_DECLARE_METATYPE(DomImage)
+Q_DECLARE_METATYPE(DomImage*)
+
+#endif
diff --git a/examples/script/context2d/environment.cpp b/examples/script/context2d/environment.cpp
new file mode 100644
index 0000000..1c1a3a6
--- /dev/null
+++ b/examples/script/context2d/environment.cpp
@@ -0,0 +1,561 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "environment.h"
+#include "qcontext2dcanvas.h"
+#include "context2d.h"
+#include <QScriptValueIterator>
+#include <QDateTime>
+
+struct FakeDomEvent
+{
+ enum KeyCodes {
+ DOM_VK_UNDEFINED = 0x0,
+ DOM_VK_RIGHT_ALT = 0x12,
+ DOM_VK_LEFT_ALT = 0x12,
+ DOM_VK_LEFT_CONTROL = 0x11,
+ DOM_VK_RIGHT_CONTROL = 0x11,
+ DOM_VK_LEFT_SHIFT = 0x10,
+ DOM_VK_RIGHT_SHIFT = 0x10,
+ DOM_VK_META = 0x9D,
+ DOM_VK_BACK_SPACE = 0x08,
+ DOM_VK_CAPS_LOCK = 0x14,
+ DOM_VK_DELETE = 0x7F,
+ DOM_VK_END = 0x23,
+ DOM_VK_ENTER = 0x0D,
+ DOM_VK_ESCAPE = 0x1B,
+ DOM_VK_HOME = 0x24,
+ DOM_VK_NUM_LOCK = 0x90,
+ DOM_VK_PAUSE = 0x13,
+ DOM_VK_PRINTSCREEN = 0x9A,
+ DOM_VK_SCROLL_LOCK = 0x91,
+ DOM_VK_SPACE = 0x20,
+ DOM_VK_TAB = 0x09,
+ DOM_VK_LEFT = 0x25,
+ DOM_VK_RIGHT = 0x27,
+ DOM_VK_UP = 0x26,
+ DOM_VK_DOWN = 0x28,
+ DOM_VK_PAGE_DOWN = 0x22,
+ DOM_VK_PAGE_UP = 0x21,
+ DOM_VK_F1 = 0x70,
+ DOM_VK_F2 = 0x71,
+ DOM_VK_F3 = 0x72,
+ DOM_VK_F4 = 0x73,
+ DOM_VK_F5 = 0x74,
+ DOM_VK_F6 = 0x75,
+ DOM_VK_F7 = 0x76,
+ DOM_VK_F8 = 0x77,
+ DOM_VK_F9 = 0x78,
+ DOM_VK_F10 = 0x79,
+ DOM_VK_F11 = 0x7A,
+ DOM_VK_F12 = 0x7B,
+ DOM_VK_F13 = 0xF000,
+ DOM_VK_F14 = 0xF001,
+ DOM_VK_F15 = 0xF002,
+ DOM_VK_F16 = 0xF003,
+ DOM_VK_F17 = 0xF004,
+ DOM_VK_F18 = 0xF005,
+ DOM_VK_F19 = 0xF006,
+ DOM_VK_F20 = 0xF007,
+ DOM_VK_F21 = 0xF008,
+ DOM_VK_F22 = 0xF009,
+ DOM_VK_F23 = 0xF00A,
+ DOM_VK_F24 = 0xF00B
+ };
+
+ static int qtToDomKey(int keyCode);
+};
+
+int FakeDomEvent::qtToDomKey(int keyCode)
+{
+ switch (keyCode) {
+ case Qt::Key_Backspace:
+ return DOM_VK_BACK_SPACE;
+ case Qt::Key_Enter:
+ return DOM_VK_ENTER;
+ case Qt::Key_Return:
+ return DOM_VK_ENTER;
+ case Qt::Key_NumLock:
+ return DOM_VK_NUM_LOCK;
+ case Qt::Key_Alt:
+ return DOM_VK_RIGHT_ALT;
+ case Qt::Key_Control:
+ return DOM_VK_LEFT_CONTROL;
+ case Qt::Key_Shift:
+ return DOM_VK_LEFT_SHIFT;
+ case Qt::Key_Meta:
+ return DOM_VK_META;
+ case Qt::Key_CapsLock:
+ return DOM_VK_CAPS_LOCK;
+ case Qt::Key_Delete:
+ return DOM_VK_DELETE;
+ case Qt::Key_End:
+ return DOM_VK_END;
+ case Qt::Key_Escape:
+ return DOM_VK_ESCAPE;
+ case Qt::Key_Home:
+ return DOM_VK_HOME;
+ case Qt::Key_Pause:
+ return DOM_VK_PAUSE;
+ case Qt::Key_Print:
+ return DOM_VK_PRINTSCREEN;
+ case Qt::Key_ScrollLock:
+ return DOM_VK_SCROLL_LOCK;
+ case Qt::Key_Left:
+ return DOM_VK_LEFT;
+ case Qt::Key_Right:
+ return DOM_VK_RIGHT;
+ case Qt::Key_Up:
+ return DOM_VK_UP;
+ case Qt::Key_Down:
+ return DOM_VK_DOWN;
+ case Qt::Key_PageDown:
+ return DOM_VK_PAGE_DOWN;
+ case Qt::Key_PageUp:
+ return DOM_VK_PAGE_UP;
+ case Qt::Key_F1:
+ return DOM_VK_F1;
+ case Qt::Key_F2:
+ return DOM_VK_F2;
+ case Qt::Key_F3:
+ return DOM_VK_F3;
+ case Qt::Key_F4:
+ return DOM_VK_F4;
+ case Qt::Key_F5:
+ return DOM_VK_F5;
+ case Qt::Key_F6:
+ return DOM_VK_F6;
+ case Qt::Key_F7:
+ return DOM_VK_F7;
+ case Qt::Key_F8:
+ return DOM_VK_F8;
+ case Qt::Key_F9:
+ return DOM_VK_F9;
+ case Qt::Key_F10:
+ return DOM_VK_F10;
+ case Qt::Key_F11:
+ return DOM_VK_F11;
+ case Qt::Key_F12:
+ return DOM_VK_F12;
+ case Qt::Key_F13:
+ return DOM_VK_F13;
+ case Qt::Key_F14:
+ return DOM_VK_F14;
+ case Qt::Key_F15:
+ return DOM_VK_F15;
+ case Qt::Key_F16:
+ return DOM_VK_F16;
+ case Qt::Key_F17:
+ return DOM_VK_F17;
+ case Qt::Key_F18:
+ return DOM_VK_F18;
+ case Qt::Key_F19:
+ return DOM_VK_F19;
+ case Qt::Key_F20:
+ return DOM_VK_F20;
+ case Qt::Key_F21:
+ return DOM_VK_F21;
+ case Qt::Key_F22:
+ return DOM_VK_F22;
+ case Qt::Key_F23:
+ return DOM_VK_F23;
+ case Qt::Key_F24:
+ return DOM_VK_F24;
+ }
+ return keyCode;
+}
+
+//! [0]
+Environment::Environment(QObject *parent)
+ : QObject(parent)
+{
+ m_engine = new QScriptEngine(this);
+
+ m_document = m_engine->newQObject(
+ new Document(this), QScriptEngine::QtOwnership,
+ QScriptEngine::ExcludeSuperClassContents);
+
+ CanvasGradientPrototype::setup(m_engine);
+
+ m_originalGlobalObject = m_engine->globalObject();
+ reset();
+}
+//! [0]
+
+Environment::~Environment()
+{
+}
+
+QScriptEngine *Environment::engine() const
+{
+ return m_engine;
+}
+
+QScriptValue Environment::document() const
+{
+ return m_document;
+}
+
+int Environment::setTimeout(const QScriptValue &expression, int delay)
+{
+ if (expression.isString() || expression.isFunction()) {
+ int timerId = startTimer(delay);
+ m_timeoutHash.insert(timerId, expression);
+ return timerId;
+ }
+ return -1;
+}
+
+void Environment::clearTimeout(int timerId)
+{
+ killTimer(timerId);
+ m_timeoutHash.remove(timerId);
+}
+
+//! [1]
+int Environment::setInterval(const QScriptValue &expression, int delay)
+{
+ if (expression.isString() || expression.isFunction()) {
+ int timerId = startTimer(delay);
+ m_intervalHash.insert(timerId, expression);
+ return timerId;
+ }
+ return -1;
+}
+
+void Environment::clearInterval(int timerId)
+{
+ killTimer(timerId);
+ m_intervalHash.remove(timerId);
+}
+
+void Environment::timerEvent(QTimerEvent *event)
+{
+ int id = event->timerId();
+ QScriptValue expression = m_intervalHash.value(id);
+ if (!expression.isValid()) {
+ expression = m_timeoutHash.value(id);
+ if (expression.isValid())
+ killTimer(id);
+ }
+ if (expression.isString()) {
+ evaluate(expression.toString());
+ } else if (expression.isFunction()) {
+ expression.call();
+ }
+ maybeEmitScriptError();
+}
+//! [1]
+
+//! [5]
+void Environment::addCanvas(QContext2DCanvas *canvas)
+{
+ m_canvases.append(canvas);
+}
+
+QContext2DCanvas *Environment::canvasByName(const QString &name) const
+{
+ for (int i = 0; i < m_canvases.size(); ++i) {
+ QContext2DCanvas *canvas = m_canvases.at(i);
+ if (canvas->objectName() == name)
+ return canvas;
+ }
+ return 0;
+}
+//! [5]
+
+QList<QContext2DCanvas*> Environment::canvases() const
+{
+ return m_canvases;
+}
+
+void Environment::reset()
+{
+ if (m_engine->isEvaluating())
+ m_engine->abortEvaluation();
+
+ {
+ QHash<int, QScriptValue>::const_iterator it;
+ for (it = m_intervalHash.constBegin(); it != m_intervalHash.constEnd(); ++it)
+ killTimer(it.key());
+ m_intervalHash.clear();
+ for (it = m_timeoutHash.constBegin(); it != m_timeoutHash.constEnd(); ++it)
+ killTimer(it.key());
+ m_timeoutHash.clear();
+ }
+
+ for (int i = 0; i < m_canvases.size(); ++i)
+ m_canvases.at(i)->reset();
+
+ QScriptValue self = m_engine->newQObject(
+ this, QScriptEngine::QtOwnership,
+ QScriptEngine::ExcludeSuperClassContents);
+
+ {
+ QScriptValueIterator it(m_originalGlobalObject);
+ while (it.hasNext()) {
+ it.next();
+ self.setProperty(it.scriptName(), it.value(), it.flags());
+ }
+ }
+
+ self.setProperty("self", self);
+ self.setProperty("window", self);
+
+ QScriptValue navigator = m_engine->newObject();
+ navigator.setProperty("appCodeName", "context2d");
+ navigator.setProperty("appMinorVersion", 1);
+ navigator.setProperty("appVersion", 1);
+ navigator.setProperty("browserLanguage", "en_US");
+ navigator.setProperty("cookieEnabled", false);
+ navigator.setProperty("cpuClass", "i686");
+ navigator.setProperty("onLine", false);
+ navigator.setProperty("platform", "bogus OS");
+ navigator.setProperty("systemLanguage", "en_US");
+ navigator.setProperty("userAgent", "Context2D/1.1");
+ navigator.setProperty("userLanguage", "en_US");
+ self.setProperty("navigator", navigator);
+
+ m_engine->setGlobalObject(self);
+
+ m_engine->collectGarbage();
+}
+
+QScriptValue Environment::evaluate(const QString &code, const QString &fileName)
+{
+ return m_engine->evaluate(code, fileName);
+}
+
+//! [2]
+QScriptValue Environment::toWrapper(QObject *object)
+{
+ return m_engine->newQObject(object, QScriptEngine::QtOwnership,
+ QScriptEngine::PreferExistingWrapperObject
+ | QScriptEngine::ExcludeSuperClassContents);
+}
+//! [2]
+
+//! [3]
+void Environment::handleEvent(QContext2DCanvas *canvas, QMouseEvent *e)
+{
+ QString type;
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ type = "mousedown"; break;
+ case QEvent::MouseButtonRelease:
+ type = "mouseup"; break;
+ case QEvent::MouseMove:
+ type = "mousemove"; break;
+ default: break;
+ }
+ if (type.isEmpty())
+ return;
+
+ QScriptValue handlerObject;
+ QScriptValue handler = eventHandler(canvas, type, &handlerObject);
+ if (!handler.isFunction())
+ return;
+
+ QScriptValue scriptEvent = newFakeDomEvent(type, toWrapper(canvas));
+ // MouseEvent
+ scriptEvent.setProperty("screenX", e->globalX(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("screenY", e->globalY(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("clientX", e->x(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("clientY", e->y(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("layerX", e->x(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("layerY", e->y(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("pageX", e->x(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("pageY", e->y(), QScriptValue::ReadOnly);
+ scriptEvent.setProperty("altKey", (e->modifiers() & Qt::AltModifier) != 0,
+ QScriptValue::ReadOnly);
+ scriptEvent.setProperty("ctrlKey", (e->modifiers() & Qt::ControlModifier) != 0,
+ QScriptValue::ReadOnly);
+ scriptEvent.setProperty("metaKey", (e->modifiers() & Qt::MetaModifier) != 0,
+ QScriptValue::ReadOnly);
+ scriptEvent.setProperty("shiftKey", (e->modifiers() & Qt::ShiftModifier) != 0,
+ QScriptValue::ReadOnly);
+ int button = 0;
+ if (e->button() == Qt::RightButton)
+ button = 2;
+ else if (e->button() == Qt::MidButton)
+ button = 1;
+ scriptEvent.setProperty("button", button);
+ scriptEvent.setProperty("relatedTarget", m_engine->nullValue(),
+ QScriptValue::ReadOnly);
+ handler.call(handlerObject, QScriptValueList() << scriptEvent);
+ maybeEmitScriptError();
+}
+//! [3]
+
+void Environment::handleEvent(QContext2DCanvas *canvas, QKeyEvent *e)
+{
+ QString type;
+ switch (e->type()) {
+ case QEvent::KeyPress:
+ type = "keydown"; break;
+ case QEvent::KeyRelease:
+ type = "keyup"; break;
+ default: break;
+ }
+ if (type.isEmpty())
+ return;
+
+ QScriptValue handlerObject;
+ QScriptValue handler = eventHandler(canvas, type, &handlerObject);
+ if (!handler.isFunction())
+ return;
+
+ QScriptValue scriptEvent = newFakeDomEvent(type, toWrapper(canvas));
+ // KeyEvent
+ scriptEvent.setProperty("isChar", !e->text().isEmpty());
+ scriptEvent.setProperty("charCode", e->text());
+ scriptEvent.setProperty("keyCode", FakeDomEvent::qtToDomKey(e->key()));
+ scriptEvent.setProperty("which", e->key());
+
+ handler.call(handlerObject, QScriptValueList() << scriptEvent);
+ maybeEmitScriptError();
+}
+
+QScriptValue Environment::eventHandler(QContext2DCanvas *canvas, const QString &type,
+ QScriptValue *who)
+{
+ QString handlerName = "on" + type;
+ QScriptValue obj = toWrapper(canvas);
+ QScriptValue handler = obj.property(handlerName);
+ if (!handler.isValid()) {
+ obj = m_document;
+ handler = obj.property(handlerName);
+ }
+ if (who && handler.isFunction())
+ *who = obj;
+ return handler;
+}
+
+//! [4]
+QScriptValue Environment::newFakeDomEvent(const QString &type, const QScriptValue &target)
+{
+ QScriptValue e = m_engine->newObject();
+ // Event
+ e.setProperty("type", type, QScriptValue::ReadOnly);
+ e.setProperty("bubbles", true, QScriptValue::ReadOnly);
+ e.setProperty("cancelable", false, QScriptValue::ReadOnly);
+ e.setProperty("target", target, QScriptValue::ReadOnly);
+ e.setProperty("currentTarget", target, QScriptValue::ReadOnly);
+ e.setProperty("eventPhase", 3); // bubbling
+ e.setProperty("timeStamp", QDateTime::currentDateTime().toTime_t());
+ // UIEvent
+ e.setProperty("detail", 0, QScriptValue::ReadOnly);
+ e.setProperty("view", m_engine->globalObject(), QScriptValue::ReadOnly);
+ return e;
+}
+//! [4]
+
+void Environment::maybeEmitScriptError()
+{
+ if (m_engine->hasUncaughtException())
+ emit scriptError(m_engine->uncaughtException());
+}
+
+
+Document::Document(Environment *env)
+ : QObject(env)
+{
+}
+
+Document::~Document()
+{
+}
+
+QScriptValue Document::getElementById(const QString &id) const
+{
+ Environment *env = qobject_cast<Environment*>(parent());
+ QContext2DCanvas *canvas = env->canvasByName(id);
+ if (!canvas)
+ return QScriptValue();
+ return env->toWrapper(canvas);
+}
+
+QScriptValue Document::getElementsByTagName(const QString &name) const
+{
+ if (name != "canvas")
+ return QScriptValue();
+ Environment *env = qobject_cast<Environment*>(parent());
+ QList<QContext2DCanvas*> list = env->canvases();
+ QScriptValue result = env->engine()->newArray(list.size());
+ for (int i = 0; i < list.size(); ++i)
+ result.setProperty(i, env->toWrapper(list.at(i)));
+ return result;
+}
+
+void Document::addEventListener(const QString &type, const QScriptValue &listener,
+ bool useCapture)
+{
+ Q_UNUSED(useCapture);
+ if (listener.isFunction()) {
+ Environment *env = qobject_cast<Environment*>(parent());
+ QScriptValue self = env->toWrapper(this);
+ self.setProperty("on" + type, listener);
+ }
+}
+
+
+QColor colorFromString(const QString &name);
+
+CanvasGradientPrototype::CanvasGradientPrototype(QObject *parent)
+ : QObject(parent)
+{
+}
+
+void CanvasGradientPrototype::addColorStop(qreal offset, const QString &color)
+{
+ CanvasGradient *self = qscriptvalue_cast<CanvasGradient*>(thisObject());
+ if (!self || (self->value.type() == QGradient::NoGradient))
+ return;
+ self->value.setColorAt(offset, colorFromString(color));
+}
+
+void CanvasGradientPrototype::setup(QScriptEngine *engine)
+{
+ CanvasGradientPrototype *proto = new CanvasGradientPrototype();
+ engine->setDefaultPrototype(qMetaTypeId<CanvasGradient>(),
+ engine->newQObject(proto, QScriptEngine::ScriptOwnership,
+ QScriptEngine::ExcludeSuperClassContents));
+}
diff --git a/examples/script/context2d/environment.h b/examples/script/context2d/environment.h
new file mode 100644
index 0000000..e47e6cb
--- /dev/null
+++ b/examples/script/context2d/environment.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ENVIRONMENT_H
+#define ENVIRONMENT_H
+
+#include <qobject.h>
+#include <qlist.h>
+#include <qhash.h>
+#include <QTimerEvent>
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include <QScriptEngine>
+#include <QScriptable>
+class QContext2DCanvas;
+
+//! [0]
+class Environment : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QScriptValue document READ document)
+public:
+ Environment(QObject *parent = 0);
+ ~Environment();
+
+ QScriptValue document() const;
+
+ void addCanvas(QContext2DCanvas *canvas);
+ QContext2DCanvas *canvasByName(const QString &name) const;
+ QList<QContext2DCanvas*> canvases() const;
+
+ QScriptValue evaluate(const QString &code,
+ const QString &fileName = QString());
+
+ QScriptValue toWrapper(QObject *object);
+
+ void handleEvent(QContext2DCanvas *canvas, QMouseEvent *e);
+ void handleEvent(QContext2DCanvas *canvas, QKeyEvent *e);
+
+ void reset();
+//! [0]
+
+ QScriptEngine *engine() const;
+
+//! [1]
+public slots:
+ int setInterval(const QScriptValue &expression, int delay);
+ void clearInterval(int timerId);
+
+ int setTimeout(const QScriptValue &expression, int delay);
+ void clearTimeout(int timerId);
+//! [1]
+
+//! [2]
+signals:
+ void scriptError(const QScriptValue &error);
+//! [2]
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QScriptValue eventHandler(QContext2DCanvas *canvas,
+ const QString &type, QScriptValue *who);
+ QScriptValue newFakeDomEvent(const QString &type,
+ const QScriptValue &target);
+ void maybeEmitScriptError();
+
+ QScriptEngine *m_engine;
+ QScriptValue m_originalGlobalObject;
+ QScriptValue m_document;
+ QList<QContext2DCanvas*> m_canvases;
+ QHash<int, QScriptValue> m_intervalHash;
+ QHash<int, QScriptValue> m_timeoutHash;
+};
+
+//! [3]
+class Document : public QObject
+{
+ Q_OBJECT
+public:
+ Document(Environment *env);
+ ~Document();
+
+public slots:
+ QScriptValue getElementById(const QString &id) const;
+ QScriptValue getElementsByTagName(const QString &name) const;
+
+ // EventTarget
+ void addEventListener(const QString &type, const QScriptValue &listener,
+ bool useCapture);
+};
+//! [3]
+
+class CanvasGradientPrototype : public QObject, public QScriptable
+{
+ Q_OBJECT
+protected:
+ CanvasGradientPrototype(QObject *parent = 0);
+public:
+ static void setup(QScriptEngine *engine);
+
+public slots:
+ void addColorStop(qreal offset, const QString &color);
+};
+
+#endif
diff --git a/examples/script/context2d/main.cpp b/examples/script/context2d/main.cpp
new file mode 100644
index 0000000..78c9df9
--- /dev/null
+++ b/examples/script/context2d/main.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+#include <QApplication>
+
+int main(int argc, char **argv)
+{
+ Q_INIT_RESOURCE(context2d);
+
+ QApplication app(argc, argv);
+ Window win;
+ win.show();
+ return app.exec();
+}
diff --git a/examples/script/context2d/qcontext2dcanvas.cpp b/examples/script/context2d/qcontext2dcanvas.cpp
new file mode 100644
index 0000000..30bb3eb
--- /dev/null
+++ b/examples/script/context2d/qcontext2dcanvas.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcontext2dcanvas.h"
+
+#include "context2d.h"
+#include "environment.h"
+#include "domimage.h"
+
+#include <QPainter>
+#include <QPaintEvent>
+
+//! [3]
+QContext2DCanvas::QContext2DCanvas(Context2D *context, Environment *env, QWidget *parent)
+ : QWidget(parent), m_context(context), m_env(env)
+{
+ QObject::connect(context, SIGNAL(changed(QImage)), this, SLOT(contentsChanged(QImage)));
+ setMouseTracking(true);
+}
+//! [3]
+
+QContext2DCanvas::~QContext2DCanvas()
+{
+}
+
+Context2D *QContext2DCanvas::context() const
+{
+ return m_context;
+}
+
+//! [0]
+QScriptValue QContext2DCanvas::getContext(const QString &str)
+{
+ if (str != "2d")
+ return QScriptValue();
+ return m_env->toWrapper(m_context);
+}
+//! [0]
+
+//! [1]
+void QContext2DCanvas::contentsChanged(const QImage &image)
+{
+ m_image = image;
+ update();
+}
+
+void QContext2DCanvas::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ p.setClipRect(e->rect());
+ p.drawImage(0, 0, m_image);
+}
+//! [1]
+
+//! [2]
+void QContext2DCanvas::mouseMoveEvent(QMouseEvent *e)
+{
+ m_env->handleEvent(this, e);
+}
+
+void QContext2DCanvas::mousePressEvent(QMouseEvent *e)
+{
+ m_env->handleEvent(this, e);
+}
+
+void QContext2DCanvas::mouseReleaseEvent(QMouseEvent *e)
+{
+ m_env->handleEvent(this, e);
+}
+
+void QContext2DCanvas::keyPressEvent(QKeyEvent *e)
+{
+ m_env->handleEvent(this, e);
+}
+
+void QContext2DCanvas::keyReleaseEvent(QKeyEvent *e)
+{
+ m_env->handleEvent(this, e);
+}
+//! [2]
+
+void QContext2DCanvas::resizeEvent(QResizeEvent *e)
+{
+ m_context->setSize(e->size().width(), e->size().height());
+}
+
+void QContext2DCanvas::resize(int width, int height)
+{
+ QWidget::resize(width, height);
+}
+
+void QContext2DCanvas::reset()
+{
+ m_context->reset();
+}
+
+void QContext2DCanvas::addEventListener(const QString &type, const QScriptValue &listener,
+ bool useCapture)
+{
+ Q_UNUSED(useCapture);
+ if (listener.isFunction()) {
+ QScriptValue self = m_env->toWrapper(this);
+ self.setProperty("on" + type, listener);
+ }
+}
diff --git a/examples/script/context2d/qcontext2dcanvas.h b/examples/script/context2d/qcontext2dcanvas.h
new file mode 100644
index 0000000..657ffc3
--- /dev/null
+++ b/examples/script/context2d/qcontext2dcanvas.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTEXT2DCANVAS_H
+#define QCONTEXT2DCANVAS_H
+
+#include <qscriptengine.h>
+#include <qscriptcontext.h>
+#include <qscriptvalue.h>
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QPaintEvent;
+class QResizeEvent;
+class QMouseEvent;
+class QKeyEvent;
+QT_END_NAMESPACE
+class Environment;
+class Context2D;
+
+//! [0]
+class QContext2DCanvas : public QWidget
+{
+ Q_OBJECT
+public:
+ QContext2DCanvas(Context2D *context, Environment *env, QWidget *parent = 0);
+ ~QContext2DCanvas();
+
+ Context2D *context() const;
+ void reset();
+
+public slots:
+ QScriptValue getContext(const QString &str);
+ void resize(int width, int height);
+
+ // EventTarget
+ void addEventListener(const QString &type, const QScriptValue &listener,
+ bool useCapture);
+
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void keyReleaseEvent(QKeyEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+
+private slots:
+ void contentsChanged(const QImage &image);
+//! [0]
+
+private:
+ Context2D *m_context;
+ Environment *m_env;
+ QImage m_image;
+};
+
+#endif
diff --git a/examples/script/context2d/scripts/alpha.js b/examples/script/context2d/scripts/alpha.js
new file mode 100644
index 0000000..23fa5d4
--- /dev/null
+++ b/examples/script/context2d/scripts/alpha.js
@@ -0,0 +1,21 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ // draw background
+ ctx.fillStyle = '#FD0';
+ ctx.fillRect(0,0,75,75);
+ ctx.fillStyle = '#6C0';
+ ctx.fillRect(75,0,75,75);
+ ctx.fillStyle = '#09F';
+ ctx.fillRect(0,75,75,75);
+ ctx.fillStyle = '#F30';
+ ctx.fillRect(75,75,75,75);
+ ctx.fillStyle = '#FFF';
+
+ // set transparency value
+ ctx.globalAlpha = 0.2;
+
+ // Draw semi transparent circles
+ for (i=0;i<7;i++){
+ ctx.beginPath();
+ ctx.arc(75,75,10+10*i,0,Math.PI*2,true);
+ ctx.fill();
+ }
diff --git a/examples/script/context2d/scripts/arc.js b/examples/script/context2d/scripts/arc.js
new file mode 100644
index 0000000..650bcda
--- /dev/null
+++ b/examples/script/context2d/scripts/arc.js
@@ -0,0 +1,30 @@
+var canvas = document.getElementById('tutorial');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext){
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ // Draw shapes
+ for (i=0;i<4;i++){
+ for(j=0;j<3;j++){
+ ctx.beginPath();
+ var x = 25+j*50; // x coordinate
+ var y = 25+i*50; // y coordinate
+ var radius = 20; // Arc radius
+ var startAngle = 0; // Starting point on circle
+ var endAngle = Math.PI+(Math.PI*j)/2; // End point on circle
+ var clockwise = i%2==0 ? false : true; // clockwise or anticlockwise
+
+ ctx.arc(x,y,radius,startAngle,endAngle, clockwise);
+
+ if (i>1){
+ ctx.fill();
+ } else {
+ ctx.stroke();
+ }
+ }
+ }
+
+ }
diff --git a/examples/script/context2d/scripts/bezier.js b/examples/script/context2d/scripts/bezier.js
new file mode 100644
index 0000000..719800e
--- /dev/null
+++ b/examples/script/context2d/scripts/bezier.js
@@ -0,0 +1,26 @@
+function drawShape() {
+// get the canvas element using the DOM
+var canvas = document.getElementById('tutorial');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext){
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ // Draw shapes
+
+ ctx.beginPath();
+ ctx.moveTo(75,40);
+ ctx.bezierCurveTo(75,37,70,25,50,25);
+ ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
+ ctx.bezierCurveTo(20,80,40,102,75,120);
+ ctx.bezierCurveTo(110,102,130,80,130,62.5);
+ ctx.bezierCurveTo(130,62.5,130,25,100,25);
+ ctx.bezierCurveTo(85,25,75,37,75,40);
+ ctx.fill();
+ ctx.globalAlpha = 0.5;
+ }
+}
+
+drawShape();
diff --git a/examples/script/context2d/scripts/clock.js b/examples/script/context2d/scripts/clock.js
new file mode 100644
index 0000000..ad287d8
--- /dev/null
+++ b/examples/script/context2d/scripts/clock.js
@@ -0,0 +1,99 @@
+function init(){
+ clock();
+ setInterval('clock()',1000);
+}
+function clock(){
+ var now = new Date();
+ var ctx = document.getElementById('tutorial').getContext('2d');
+ ctx.save();
+ ctx.clearRect(0,0,150,150);
+ ctx.translate(75,75);
+ ctx.scale(0.4,0.4);
+ ctx.rotate(-Math.PI/2);
+ ctx.strokeStyle = "black";
+ ctx.fillStyle = "white";
+ ctx.lineWidth = 8;
+ ctx.lineCap = "round";
+
+ // Hour marks
+ ctx.save();
+ ctx.beginPath();
+ for (i=0;i<12;i++){
+ ctx.rotate(Math.PI/6);
+ ctx.moveTo(100,0);
+ ctx.lineTo(120,0);
+ }
+ ctx.stroke();
+ ctx.restore();
+
+ // Minute marks
+ ctx.save();
+ ctx.lineWidth = 5;
+ ctx.beginPath();
+ for (i=0;i<60;i++){
+ if (i%5!=0) {
+ ctx.moveTo(117,0);
+ ctx.lineTo(120,0);
+ }
+ ctx.rotate(Math.PI/30);
+ }
+ ctx.stroke();
+ ctx.restore();
+
+ var sec = now.getSeconds();
+ var min = now.getMinutes();
+ var hr = now.getHours();
+ hr = hr>=12 ? hr-12 : hr;
+
+ ctx.fillStyle = "black";
+
+ // write Hours
+ ctx.save();
+ ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
+ ctx.lineWidth = 14;
+ ctx.beginPath();
+ ctx.moveTo(-20,0);
+ ctx.lineTo(80,0);
+ ctx.stroke();
+ ctx.restore();
+
+ // write Minutes
+ ctx.save();
+ ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
+ ctx.lineWidth = 10;
+ ctx.beginPath();
+ ctx.moveTo(-28,0);
+ ctx.lineTo(112,0);
+ ctx.stroke();
+ ctx.restore();
+
+ // Write seconds
+ ctx.save();
+ ctx.rotate(sec * Math.PI/30);
+ ctx.strokeStyle = "#D40000";
+ ctx.fillStyle = "#D40000";
+ ctx.lineWidth = 6;
+ ctx.beginPath();
+ ctx.moveTo(-30,0);
+ ctx.lineTo(83,0);
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.arc(0,0,10,0,Math.PI*2,true);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(95,0,10,0,Math.PI*2,true);
+ ctx.stroke();
+ ctx.fillStyle = "#555";
+ ctx.arc(0,0,3,0,Math.PI*2,true);
+ ctx.fill();
+ ctx.restore();
+
+ ctx.beginPath();
+ ctx.lineWidth = 14;
+ ctx.strokeStyle = '#325FA2';
+ ctx.arc(0,0,142,0,Math.PI*2,true);
+ ctx.stroke();
+
+ ctx.restore();
+}
+init();
diff --git a/examples/script/context2d/scripts/fill1.js b/examples/script/context2d/scripts/fill1.js
new file mode 100644
index 0000000..db5eeb7
--- /dev/null
+++ b/examples/script/context2d/scripts/fill1.js
@@ -0,0 +1,8 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ for (i=0;i<6;i++){
+ for (j=0;j<6;j++){
+ ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
+ Math.floor(255-42.5*j) + ',0)';
+ ctx.fillRect(j*25,i*25,25,25);
+ }
+ }
diff --git a/examples/script/context2d/scripts/grad.js b/examples/script/context2d/scripts/grad.js
new file mode 100644
index 0000000..24ccfbb
--- /dev/null
+++ b/examples/script/context2d/scripts/grad.js
@@ -0,0 +1,20 @@
+ var ctx = document.getElementById('tutorial').getContext('2d');
+
+ // Create gradients
+ var lingrad = ctx.createLinearGradient(0,0,0,150);
+ lingrad.addColorStop(0, '#00ABEB');
+ lingrad.addColorStop(0.5, '#fff');
+ lingrad.addColorStop(0.5, '#66CC00');
+ lingrad.addColorStop(1, '#fff');
+
+ var lingrad2 = ctx.createLinearGradient(0,50,0,95);
+ lingrad2.addColorStop(0.5, '#000');
+ lingrad2.addColorStop(1, 'rgba(0,0,0,0)');
+
+ // assign gradients to fill and stroke styles
+ ctx.fillStyle = lingrad;
+ ctx.strokeStyle = lingrad2;
+
+ // draw shapes
+ ctx.fillRect(10,10,130,130);
+ ctx.strokeRect(50,50,50,50);
diff --git a/examples/script/context2d/scripts/linecap.js b/examples/script/context2d/scripts/linecap.js
new file mode 100644
index 0000000..18ceb23
--- /dev/null
+++ b/examples/script/context2d/scripts/linecap.js
@@ -0,0 +1,24 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ var lineCap = ['butt','round','square'];
+
+ // Draw guides
+ ctx.save();
+ ctx.strokeStyle = '#09f';
+ ctx.beginPath();
+ ctx.moveTo(10,10);
+ ctx.lineTo(140,10);
+ ctx.moveTo(10,140);
+ ctx.lineTo(140,140);
+ ctx.stroke();
+
+ // Draw lines
+ ctx.strokeStyle = 'black';
+ for (i=0;i<lineCap.length;i++){
+ ctx.lineWidth = 15;
+ ctx.lineCap = lineCap[i];
+ ctx.beginPath();
+ ctx.moveTo(25+i*50,10);
+ ctx.lineTo(25+i*50,140);
+ ctx.stroke();
+ }
+ ctx.restore();
diff --git a/examples/script/context2d/scripts/linestye.js b/examples/script/context2d/scripts/linestye.js
new file mode 100644
index 0000000..728e3e6
--- /dev/null
+++ b/examples/script/context2d/scripts/linestye.js
@@ -0,0 +1,10 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ctx.save();
+ for (i=0;i<10;i++){
+ ctx.lineWidth = 1+i;
+ ctx.beginPath();
+ ctx.moveTo(5+i*14,5);
+ ctx.lineTo(5+i*14,140);
+ ctx.stroke();
+ }
+ctx.restore(); \ No newline at end of file
diff --git a/examples/script/context2d/scripts/moveto.js b/examples/script/context2d/scripts/moveto.js
new file mode 100644
index 0000000..73c4e8d
--- /dev/null
+++ b/examples/script/context2d/scripts/moveto.js
@@ -0,0 +1,20 @@
+var canvas = document.getElementById('tutorial');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext){
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ // Draw shapes
+ ctx.beginPath();
+ ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
+ ctx.moveTo(110,75);
+ ctx.arc(75,75,35,0,Math.PI,false); // Mouth
+ ctx.moveTo(65,65);
+ ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye
+ ctx.moveTo(95,65);
+ ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye
+ ctx.stroke();
+
+ }
diff --git a/examples/script/context2d/scripts/moveto2.js b/examples/script/context2d/scripts/moveto2.js
new file mode 100644
index 0000000..021f47b
--- /dev/null
+++ b/examples/script/context2d/scripts/moveto2.js
@@ -0,0 +1,24 @@
+var canvas = document.getElementById('tutorial');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext){
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ // Filled triangle
+ ctx.beginPath();
+ ctx.moveTo(25,25);
+ ctx.lineTo(105,25);
+ ctx.lineTo(25,105);
+ ctx.fill();
+
+ // Stroked triangle
+ ctx.beginPath();
+ ctx.moveTo(125,125);
+ ctx.lineTo(125,45);
+ ctx.lineTo(45,125);
+ ctx.closePath();
+ ctx.stroke();
+
+ }
diff --git a/examples/script/context2d/scripts/pacman.js b/examples/script/context2d/scripts/pacman.js
new file mode 100644
index 0000000..af3750f
--- /dev/null
+++ b/examples/script/context2d/scripts/pacman.js
@@ -0,0 +1,83 @@
+function roundedRect(ctx,x,y,width,height,radius){
+ ctx.beginPath();
+ ctx.moveTo(x,y+radius);
+ ctx.lineTo(x,y+height-radius);
+ ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
+ ctx.lineTo(x+width-radius,y+height);
+ ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
+ ctx.lineTo(x+width,y+radius);
+ ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
+ ctx.lineTo(x+radius,y);
+ ctx.quadraticCurveTo(x,y,x,y+radius);
+ ctx.stroke();
+}
+
+var canvas = document.getElementById('tutorial');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext){
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ // Draw shapes
+ roundedRect(ctx,12,12,150,150,15);
+ roundedRect(ctx,19,19,150,150,9);
+ roundedRect(ctx,53,53,49,33,10);
+ roundedRect(ctx,53,119,49,16,6);
+ roundedRect(ctx,135,53,49,33,10);
+ roundedRect(ctx,135,119,25,49,10);
+
+ // Character 1
+ ctx.beginPath();
+ ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false);
+ ctx.lineTo(34,37);
+ ctx.fill();
+
+ // blocks
+ for(i=0;i<8;i++){
+ ctx.fillRect(51+i*16,35,4,4);
+ }
+ for(i=0;i<6;i++){
+ ctx.fillRect(115,51+i*16,4,4);
+ }
+ for(i=0;i<8;i++){
+ ctx.fillRect(51+i*16,99,4,4);
+ }
+
+ // character 2
+ ctx.beginPath();
+ ctx.moveTo(83,116);
+ ctx.lineTo(83,102);
+
+ ctx.bezierCurveTo(83,94,89,88,97,88);
+ ctx.bezierCurveTo(105,88,111,94,111,102);
+ ctx.lineTo(111,116);
+ ctx.lineTo(106.333,111.333);
+ ctx.lineTo(101.666,116);
+ ctx.lineTo(97,111.333);
+ ctx.lineTo(92.333,116);
+ ctx.lineTo(87.666,111.333);
+ ctx.lineTo(83,116);
+ ctx.fill();
+ ctx.fillStyle = "white";
+ ctx.beginPath();
+ ctx.moveTo(91,96);
+ ctx.bezierCurveTo(88,96,87,99,87,101);
+ ctx.bezierCurveTo(87,103,88,106,91,106);
+ ctx.bezierCurveTo(94,106,95,103,95,101);
+ ctx.bezierCurveTo(95,99,94,96,91,96);
+ ctx.moveTo(103,96);
+ ctx.bezierCurveTo(100,96,99,99,99,101);
+ ctx.bezierCurveTo(99,103,100,106,103,106);
+ ctx.bezierCurveTo(106,106,107,103,107,101);
+ ctx.bezierCurveTo(107,99,106,96,103,96);
+ ctx.fill();
+ ctx.fillStyle = "black";
+ ctx.beginPath();
+ ctx.arc(101,102,2,0,Math.PI*2,true);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(89,102,2,0,Math.PI*2,true);
+ ctx.fill();
+ }
diff --git a/examples/script/context2d/scripts/plasma.js b/examples/script/context2d/scripts/plasma.js
new file mode 100644
index 0000000..1aa9294
--- /dev/null
+++ b/examples/script/context2d/scripts/plasma.js
@@ -0,0 +1,58 @@
+var counter = 0;
+
+var PIXEL_SIZE = 4;
+
+var temp_1 = 0;
+
+function init()
+{
+ setInterval('render()',50);
+}
+
+function dist(a, b, c, d)
+{
+ return Math.sqrt((a - c) * (a - c) + (b - d) * (b - d));
+}
+
+
+function render()
+{
+ var canvas = document.getElementById('tutorial');
+ canvas.resize(128, 128);
+ var ctx = canvas.getContext('2d');
+ ctx.save();
+
+ var time = counter * 5;
+
+
+ for( y = 0; y < 128; y+=PIXEL_SIZE) {
+ for( x = 0 ; x < 128; x+=PIXEL_SIZE) {
+
+
+ var temp_val = Math.floor(Math.sin(dist(x + time, y, 128.0, 128.0) / 8.0)
+ + Math.sin(dist(x, y, 64.0, 64.0) / 8.0)
+ + Math.sin(dist(x, y + time / 7, 192.0, 64) / 7.0)
+ + Math.sin(dist(x, y, 192.0, 100.0) / 8.0));
+
+
+
+
+ var temp_col = Math.floor((2 + temp_val) * 50);
+
+ var rand_red = temp_col * 3;
+ var rand_green = temp_col ;
+ var rand_blue = 128 - temp_col;
+
+ ctx.fillStyle = "rgb("+rand_red+","+rand_green+","+rand_blue+")";
+
+ ctx.fillRect(x,y,PIXEL_SIZE,PIXEL_SIZE);
+ }
+ }
+
+
+ ctx.restore();
+ counter++;
+
+}
+
+init();
diff --git a/examples/script/context2d/scripts/pong.js b/examples/script/context2d/scripts/pong.js
new file mode 100644
index 0000000..2bff053
--- /dev/null
+++ b/examples/script/context2d/scripts/pong.js
@@ -0,0 +1,235 @@
+// globals
+playarea_canvas = document.getElementById('tutorial');
+playarea_canvas.resize(320,200);
+playarea = playarea_canvas.getContext('2d');
+//p1_scr = document.getElementById('p1_scr');
+//p2_scr = document.getElementById('p2_scr');
+//status_msg = document.getElementById('status');
+//debug = document.getElementById('debug');
+ball_direction = 0;
+up = -1;
+down = 1;
+
+//key codes
+key_up = 38;
+key_down = 40;
+key_W = 87;
+key_S = 83;
+key_pause = 32;
+
+speed = 2; //controls the speed of the ball
+paddle_inc = 10; //how many pixels paddle can move in either direction
+pause = false;
+
+player_1 = 0; //player IDs
+player_2 = 1;
+player_1_scr = 0; //player scores
+player_2_scr = 0;
+player_1_direction = null; //null = no movement whatsoever
+player_2_direction = null;
+
+pa = new Array();
+divider = new Array();
+paddle_1 = new Array();
+paddle_2 = new Array();
+ball = new Array();
+
+
+function sleep(numberMillis)
+{
+ var now = new Date();
+ var exitTime = now.getTime() + numberMillis;
+ while (true) {
+ now = new Date();
+ if (now.getTime() > exitTime)
+ return;
+ }
+}
+
+function init()
+{
+ pa['width'] = 150;
+ pa['height'] = 140;
+ pa['player_margin'] = 10; //area behind player paddles
+ pa['foreground'] = "#FFFFFF";
+ pa['background'] = "#000000";
+
+ divider['pos'] = pa['width']/2;
+ divider['width'] = 4;
+
+ paddle_1['width'] = 8;
+ paddle_1['height'] = 64;
+ paddle_1['x'] = pa['player_margin'];
+ paddle_1['y'] = (pa['height'] /2 ) - (paddle_1['height'] / 2);
+
+ paddle_2['width'] = 8;
+ paddle_2['height'] = 64;
+ paddle_2['x'] = (pa['width'] - pa['player_margin'] - paddle_2['width']);
+ paddle_2['y'] = (pa['height'] /2 ) - (paddle_2['height'] / 2);
+
+ ball['width'] = 10;
+ ball['height'] = 10;
+ ball['x'] = (pa['width']/2) - (ball['width'] / 2);
+ ball['y'] = (pa['height']/2) - (ball['height'] / 2);
+
+ ball_direction = Math.random() * 360; //initialize ball direction, which is determined by angle, at random
+ speed = 2;
+}
+
+function renderPlayarea()
+{
+ playarea.beginPath();
+
+ playarea.clearRect(0,0,pa['width'],pa['height']);
+ playarea.fillStyle = pa['background'];
+ playarea.strokeStyle = pa['foreground'];
+ playarea.fillRect(0,0, pa['width'], pa['height']);
+
+ //move paddles
+ if(player_1_direction != null)
+ {
+ if(player_1_direction == up)
+ paddle_1['y'] = paddle_1['y'] - paddle_inc;
+ else
+ paddle_1['y'] = paddle_1['y'] + paddle_inc;
+ }
+ if(player_2_direction != null)
+ {
+ if(player_2_direction == up)
+ paddle_2['y'] = paddle_2['y'] - paddle_inc;
+ else
+ paddle_2['y'] = paddle_2['y'] + paddle_inc;
+ }
+ playarea.rect(paddle_1['x'],paddle_1['y'],paddle_1['width'],paddle_1['height']);
+ playarea.rect(paddle_2['x'],paddle_2['y'],paddle_2['width'],paddle_2['height']);
+
+ //move ball
+ playarea.rect(ball['x'], ball['y'], ball['width'], ball['height']);
+ ball['x'] = ball['x'] + Math.cos((ball_direction)*Math.PI/180) * speed;
+ ball['y'] = ball['y'] + Math.sin((ball_direction)*Math.PI/180) * speed;
+
+ playarea.fillStyle = pa['foreground'];
+ playarea.fill();
+
+ playarea.beginPath();
+ //redraw divider
+ playarea.lineWidth = divider['width'];
+ playarea.lineTo(divider['pos'], 0);
+ playarea.lineTo(divider['pos'], pa['height'] = 200);
+ playarea.lineWidth = 1;
+
+ playarea.stroke();
+ playarea.closePath();
+}
+
+function testCollisions()
+{
+ //make sure paddles don't go beyond play area
+ if(((paddle_1['y'] <= 0) && (player_1_direction == up)) || ((paddle_1['y'] >= (pa['height'] - paddle_1['height'])) && (player_1_direction == down)))
+ player_1_direction = null;
+ if(((paddle_2['y'] <= 0) && (player_2_direction == up)) || ((paddle_2['y'] >= (pa['height'] - paddle_2['height'])) && (player_2_direction == down)))
+ player_2_direction = null;
+
+ //check to see if ball went beyond paddles, and if so, score accordingly and reset playarea
+ if(ball['x'] <= 0)
+ {
+ setScore(player_2);
+ init()
+ sleep(1000);
+ }
+ if(ball['x'] >= (pa['width'] - ball['width']))
+ {
+ setScore(player_1);
+ init();
+ sleep(1000);
+ }
+
+ //check to see if ball hit top or bottom wall. if so, change direction
+ if((ball['y'] >= (pa['height'] - ball['height'])) || ball['y'] <= 0)
+ ball_direction = -ball_direction;
+
+ //check to see if the ball hit a paddle, and if so, change ball angle dependant on where it hit the paddle
+ if((ball['x'] <= (paddle_1['x'] + paddle_1['width'])) && (ball['y'] >= paddle_1['y']) && (ball['y'] <= (paddle_1['y'] + paddle_1['height'])))
+ {
+ ball_direction = -ball_direction/2;
+ speed += .5;
+ }
+ if(((ball['x'] + ball['width']) >= paddle_2['x']) && (ball['y'] >= paddle_2['y']) && (ball['y'] <= (paddle_2['y'] + paddle_2['height'])))
+ {
+ ball_direction = (180+ball_direction)/2;
+ speed += .5;
+ }
+}
+
+function setScore(p)
+{
+ if(p == player_1)
+ {
+ player_1_scr++;
+ //p1_scr.firstChild.nodeValue = player_1_scr;
+ }
+ if(p == player_2)
+ {
+ player_2_scr++;
+ //p2_scr.firstChild.nodeValue = player_2_scr;
+ }
+}
+
+
+//handle input
+document.onkeydown = function(ev)
+{
+ switch(ev.keyCode)
+ {
+ case key_W:
+ player_1_direction = up;
+ break;
+ case key_S:
+ player_1_direction = down;
+ break;
+ case key_up:
+ player_2_direction = up;
+ break;
+ case key_down:
+ player_2_direction = down;
+ break;
+ }
+}
+
+document.onkeyup = function(ev)
+{
+ switch(ev.keyCode)
+ {
+ case key_W:
+ case key_S:
+ player_1_direction = null;
+ break;
+ case key_up:
+ case key_down:
+ player_2_direction = null;
+ break;
+ case key_pause:
+ if(pause == false)
+ {
+ clearInterval(game);
+ //status_msg.style.visibility = "visible";
+ pause = true;
+ }
+ else
+ {
+ game = setInterval(main, 25);
+ //status_msg.style.visibility = "hidden";
+ pause = false;
+ }
+ break;
+ }
+}
+
+function main()
+{
+ testCollisions();
+ renderPlayarea();
+}
+
+init();
+game = setInterval(main, 25);
diff --git a/examples/script/context2d/scripts/quad.js b/examples/script/context2d/scripts/quad.js
new file mode 100644
index 0000000..ad3a0d5
--- /dev/null
+++ b/examples/script/context2d/scripts/quad.js
@@ -0,0 +1,21 @@
+var canvas = document.getElementById('tutorial');
+
+ // Make sure we don't execute when canvas isn't supported
+ if (canvas.getContext){
+
+ // use getContext to use the canvas for drawing
+ var ctx = canvas.getContext('2d');
+
+ // Draw shapes
+
+ ctx.beginPath();
+ ctx.moveTo(75,25);
+ ctx.quadraticCurveTo(25,25,25,62.5);
+ ctx.quadraticCurveTo(25,100,50,100);
+ ctx.quadraticCurveTo(50,120,30,125);
+ ctx.quadraticCurveTo(60,120,65,100);
+ ctx.quadraticCurveTo(125,100,125,62.5);
+ ctx.quadraticCurveTo(125,25,75,25);
+ ctx.stroke();
+
+ }
diff --git a/examples/script/context2d/scripts/rgba.js b/examples/script/context2d/scripts/rgba.js
new file mode 100644
index 0000000..a4e5e9a
--- /dev/null
+++ b/examples/script/context2d/scripts/rgba.js
@@ -0,0 +1,19 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+
+ // Draw background
+ ctx.fillStyle = 'rgb(255,221,0)';
+ ctx.fillRect(0,0,150,37.5);
+ ctx.fillStyle = 'rgb(102,204,0)';
+ ctx.fillRect(0,37.5,150,37.5);
+ ctx.fillStyle = 'rgb(0,153,255)';
+ ctx.fillRect(0,75,150,37.5);
+ ctx.fillStyle = 'rgb(255,51,0)';
+ ctx.fillRect(0,112.5,150,37.5);
+
+ // Draw semi transparent rectangles
+ for (i=0;i<10;i++){
+ ctx.fillStyle = 'rgba(255,255,255,'+(i+1)/10+')';
+ for (j=0;j<4;j++){
+ ctx.fillRect(5+i*14,5+j*37.5,14,27.5)
+ }
+ }
diff --git a/examples/script/context2d/scripts/rotate.js b/examples/script/context2d/scripts/rotate.js
new file mode 100644
index 0000000..c7ef369
--- /dev/null
+++ b/examples/script/context2d/scripts/rotate.js
@@ -0,0 +1,16 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ ctx.translate(75,75);
+
+ for (i=1;i<6;i++){ // Loop through rings (from inside to out)
+ ctx.save();
+ ctx.fillStyle = 'rgb('+(51*i)+','+(255-51*i)+',255)';
+
+ for (j=0;j<i*6;j++){ // draw individual dots
+ ctx.rotate(Math.PI*2/(i*6));
+ ctx.beginPath();
+ ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
+ ctx.fill();
+ }
+
+ ctx.restore();
+ }
diff --git a/examples/script/context2d/scripts/scale.js b/examples/script/context2d/scripts/scale.js
new file mode 100644
index 0000000..75ef865
--- /dev/null
+++ b/examples/script/context2d/scripts/scale.js
@@ -0,0 +1,67 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ ctx.strokeStyle = "#fc0";
+ ctx.lineWidth = 1.5;
+ ctx.fillRect(0,0,300,300);
+
+ // Uniform scaling
+ ctx.save()
+ ctx.translate(50,50);
+ drawSpirograph(ctx,22,6,5); // no scaling
+
+ ctx.translate(100,0);
+ ctx.scale(0.75,0.75);
+ drawSpirograph(ctx,22,6,5);
+
+ ctx.translate(133.333,0);
+ ctx.scale(0.75,0.75);
+ drawSpirograph(ctx,22,6,5);
+ ctx.restore();
+
+ // Non uniform scaling (y direction)
+ ctx.strokeStyle = "#0cf";
+ ctx.save()
+ ctx.translate(50,150);
+ ctx.scale(1,0.75);
+ drawSpirograph(ctx,22,6,5);
+
+ ctx.translate(100,0);
+ ctx.scale(1,0.75);
+ drawSpirograph(ctx,22,6,5);
+
+ ctx.translate(100,0);
+ ctx.scale(1,0.75);
+ drawSpirograph(ctx,22,6,5);
+ ctx.restore();
+
+ // Non uniform scaling (x direction)
+ ctx.strokeStyle = "#cf0";
+ ctx.save()
+ ctx.translate(50,250);
+ ctx.scale(0.75,1);
+ drawSpirograph(ctx,22,6,5);
+
+ ctx.translate(133.333,0);
+ ctx.scale(0.75,1);
+ drawSpirograph(ctx,22,6,5);
+
+ ctx.translate(177.777,0);
+ ctx.scale(0.75,1);
+ drawSpirograph(ctx,22,6,5);
+ ctx.restore();
+function drawSpirograph(ctx,R,r,O){
+ var x1 = R-O;
+ var y1 = 0;
+ var i = 1;
+ ctx.beginPath();
+ ctx.moveTo(x1,y1);
+ do {
+ if (i>20000) break;
+ var x2 = (R+r)*Math.cos(i*Math.PI/72) - (r+O)*Math.cos(((R+r)/r)*(i*Math.PI/72))
+ var y2 = (R+r)*Math.sin(i*Math.PI/72) - (r+O)*Math.sin(((R+r)/r)*(i*Math.PI/72))
+ ctx.lineTo(x2,y2);
+ x1 = x2;
+ y1 = y2;
+ i++;
+ } while (x2 != R-O && y2 != 0 );
+ ctx.stroke();
+}
diff --git a/examples/script/context2d/scripts/stroke1.js b/examples/script/context2d/scripts/stroke1.js
new file mode 100644
index 0000000..0561a52
--- /dev/null
+++ b/examples/script/context2d/scripts/stroke1.js
@@ -0,0 +1,10 @@
+var ctx = document.getElementById('tutorial').getContext('2d');
+ for (i=0;i<6;i++){
+ for (j=0;j<6;j++){
+ ctx.strokeStyle = 'rgb(0,' + Math.floor(255-42.5*i) + ',' +
+ Math.floor(255-42.5*j) + ')';
+ ctx.beginPath();
+ ctx.arc(12.5+j*25,12.5+i*25,10,0,Math.PI*2,true);
+ ctx.stroke();
+ }
+ }
diff --git a/examples/script/context2d/scripts/translate.js b/examples/script/context2d/scripts/translate.js
new file mode 100644
index 0000000..7c94433
--- /dev/null
+++ b/examples/script/context2d/scripts/translate.js
@@ -0,0 +1,29 @@
+ var ctx = document.getElementById('tutorial').getContext('2d');
+ ctx.fillRect(0,0,300,300);
+ for (var i=0;i<3;i++) {
+ for (var j=0;j<3;j++) {
+ ctx.save();
+ ctx.strokeStyle = "#9CFF00";
+ ctx.translate(50+j*100,50+i*100);
+ drawSpirograph(ctx,20*(j+2)/(j+1),-8*(i+3)/(i+1),10);
+ ctx.restore();
+ }
+ }
+
+function drawSpirograph(ctx,R,r,O){
+ var x1 = R-O;
+ var y1 = 0;
+ var i = 1;
+ ctx.beginPath();
+ ctx.moveTo(x1,y1);
+ do {
+ if (i>20000) break;
+ var x2 = (R+r)*Math.cos(i*Math.PI/72) - (r+O)*Math.cos(((R+r)/r)*(i*Math.PI/72))
+ var y2 = (R+r)*Math.sin(i*Math.PI/72) - (r+O)*Math.sin(((R+r)/r)*(i*Math.PI/72))
+ ctx.lineTo(x2,y2);
+ x1 = x2;
+ y1 = y2;
+ i++;
+ } while (x2 != R-O && y2 != 0 );
+ ctx.stroke();
+}
diff --git a/examples/script/context2d/window.cpp b/examples/script/context2d/window.cpp
new file mode 100644
index 0000000..a93bf30
--- /dev/null
+++ b/examples/script/context2d/window.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+#include "environment.h"
+#include "context2d.h"
+#include "qcontext2dcanvas.h"
+#include <QHBoxLayout>
+#include <QListWidget>
+#include <QDir>
+#include <QMessageBox>
+
+#ifndef QT_NO_SCRIPTTOOLS
+#include <QAction>
+#include <QApplication>
+#include <QMainWindow>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QScriptEngineDebugger>
+#endif
+
+static QString scriptsDir()
+{
+ if (QFile::exists("./scripts"))
+ return "./scripts";
+ return ":/scripts";
+}
+
+//! [0]
+Window::Window(QWidget *parent)
+ : QWidget(parent)
+{
+ m_env = new Environment(this);
+ QObject::connect(m_env, SIGNAL(scriptError(QScriptValue)),
+ this, SLOT(reportScriptError(QScriptValue)));
+
+ Context2D *context = new Context2D(this);
+ context->setSize(150, 150);
+ m_canvas = new QContext2DCanvas(context, m_env, this);
+ m_canvas->setFixedSize(context->size());
+ m_canvas->setObjectName("tutorial");
+ m_env->addCanvas(m_canvas);
+//! [0]
+
+#ifndef QT_NO_SCRIPTTOOLS
+ QVBoxLayout *vbox = new QVBoxLayout();
+ vbox->addWidget(m_canvas);
+ m_debugButton = new QPushButton(tr("Run in Debugger"));
+ connect(m_debugButton, SIGNAL(clicked()), this, SLOT(runInDebugger()));
+ vbox->addWidget(m_debugButton);
+#endif
+
+ QHBoxLayout *hbox = new QHBoxLayout(this);
+ m_view = new QListWidget(this);
+ m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hbox->addWidget(m_view);
+#ifndef QT_NO_SCRIPTTOOLS
+ hbox->addLayout(vbox);
+#else
+ hbox->addWidget(m_canvas);
+#endif
+
+//! [1]
+ QDir dir(scriptsDir());
+ QFileInfoList entries = dir.entryInfoList(QStringList() << "*.js");
+ for (int i = 0; i < entries.size(); ++i)
+ m_view->addItem(entries.at(i).fileName());
+ connect(m_view, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
+ this, SLOT(selectScript(QListWidgetItem*)));
+//! [1]
+
+#ifndef QT_NO_SCRIPTTOOLS
+ m_debugger = new QScriptEngineDebugger(this);
+ m_debugger->attachTo(m_env->engine());
+ m_debugWindow = m_debugger->standardWindow();
+ m_debugWindow->setWindowModality(Qt::ApplicationModal);
+ m_debugWindow->resize(1280, 704);
+#endif
+
+ setWindowTitle(tr("Context 2D"));
+}
+
+//! [2]
+void Window::selectScript(QListWidgetItem *item)
+{
+ QString fileName = item->text();
+ runScript(fileName, /*debug=*/false);
+}
+//! [2]
+
+void Window::reportScriptError(const QScriptValue &error)
+{
+ QMessageBox::warning(this, tr("Context 2D"), tr("Line %0: %1")
+ .arg(error.property("lineNumber").toInt32())
+ .arg(error.toString()));
+}
+
+#ifndef QT_NO_SCRIPTTOOLS
+//! [3]
+void Window::runInDebugger()
+{
+ QListWidgetItem *item = m_view->currentItem();
+ if (item) {
+ QString fileName = item->text();
+ runScript(fileName, /*debug=*/true);
+ }
+}
+//! [3]
+#endif
+
+//! [4]
+void Window::runScript(const QString &fileName, bool debug)
+{
+ QFile file(scriptsDir() + "/" + fileName);
+ file.open(QIODevice::ReadOnly);
+ QString contents = file.readAll();
+ file.close();
+ m_env->reset();
+
+#ifndef QT_NO_SCRIPTTOOLS
+ if (debug)
+ m_debugger->action(QScriptEngineDebugger::InterruptAction)->trigger();
+#else
+ Q_UNUSED(debug);
+#endif
+
+ QScriptValue ret = m_env->evaluate(contents, fileName);
+
+#ifndef QT_NO_SCRIPTTOOLS
+ m_debugWindow->hide();
+#endif
+
+ if (ret.isError())
+ reportScriptError(ret);
+}
+//! [4]
diff --git a/examples/script/context2d/window.h b/examples/script/context2d/window.h
new file mode 100644
index 0000000..a0aff8e
--- /dev/null
+++ b/examples/script/context2d/window.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <QWidget>
+class Environment;
+class QContext2DCanvas;
+QT_BEGIN_NAMESPACE
+class QListWidget;
+class QListWidgetItem;
+class QMainWindow;
+class QPushButton;
+class QScriptValue;
+class QScriptEngineDebugger;
+QT_END_NAMESPACE
+
+class Window : public QWidget
+{
+ Q_OBJECT
+public:
+ Window(QWidget *parent = 0);
+private slots:
+ void selectScript(QListWidgetItem *item);
+ void reportScriptError(const QScriptValue &value);
+#ifndef QT_NO_SCRIPTTOOLS
+ void runInDebugger();
+#endif
+private:
+ void runScript(const QString &fileName, bool debug);
+
+ QListWidget *m_view;
+ Environment *m_env;
+ QContext2DCanvas *m_canvas;
+#ifndef QT_NO_SCRIPTTOOLS
+ QScriptEngineDebugger *m_debugger;
+ QPushButton *m_debugButton;
+ QMainWindow *m_debugWindow;
+#endif
+};
+
+#endif // WINDOW_H